您的位置:首页 > Web前端 > JavaScript

JavaScript学习小结(二)

2013-02-07 20:35 190 查看
关于JavaScript的版本

目前Js标准有两个支撑,分别为ECMA-262和ECMA-357.357是针对262的一个XML扩展。

关于JavaScript的运行环境

只要有解释器,客户端/服务器端均可。由于浏览器默认装载了解释器,所以通过浏览器学习Js是很方便的。

关于JavaScript的类型变换

基本数据类型之间,对象和基本数据类型是可以自动转换的。

基本数据类型->对象的转换,涉及到一个概念--瞬态对象。所谓的瞬态,是指被系统临时创建用后就丢弃的。

如下代码即为瞬态对象的典型例子。

var s = 'abc';
console.log(s.length);


var s = 'abc';
console.log(s.length);


至于对象->基本数据类型的转换,则可能涉及到对象的toString,valueOf方法。

关于传值和传址

基本数据类型:传值

函数和数组:传址。关于这一点还是和传统Java有区别的,JavaScript中更像是引用的传值。以下的代码较好地解释了这一点。

// This is another version of the add_to_totals() function. It doesn't
// work, though, because instead of changing the array itself, it tries to
// change the reference to the array.
function add_to_totals2(totals, x)
{
newtotals = new Array(3);
newtotals[0] = totals[0] + x;
newtotals[1] = totals[1] + x;
newtotals[2] = totals[2] + x;
totals = newtotals;  // This line has no effect outside of the function
}


字符串:比较特殊,可以认为是传值。这一点和Java不同,值得注意。

关于变量的重复声明

对变量没有任何影响。

关于未定义的变量

未声明的变量不能直接读,否则会发生错误;但却可以直接赋值,赋值的过程中系统隐式声明它。

关于变量的作用域

全局变量就是全局对象的属性,局部变量就是调用对象的属性。调用对象和全局对象共同构成了作用域链(Scope chain)。变量名解析(variable name resolution)就是在这个作用域链中查询变量的过程。按照我的理解,局部变量所在的调用对象实际上和函数相关,它是指函数被调用时创建的。该调用对象的一个属性被初始化成一个名叫 arguments 的属性,它引用了这个函数的 Arguments 对象--函数的实际参数。所有用 var 语句声明的本地变量也被定义在这个调用对象里。这个时候,调用对象处在作用域链的头部,本地变量、函数形式参数和 Arguments 对象全部都在这个函数的范围里了。其实,由于JavaScript是通过词法来划分作用域的,当一个函数在定义的时候,其作用域链就形成了,并成为该函数的内部状态。只不过当调用的时候,所创建的调用对象被添加到定义时创建的作用域链的头部。

关于闭包

代码和作用域的综合体叫做闭包。所有的JavaScript函数都是闭包。


只有当一个嵌套函数被到处到它所定义的作用域外时,这种闭包才是有趣的。--摘自犀牛书



关于类,构造函数和原型

JavaScript还不支持真正的类,其所为的类为伪类(pseudoclass)。构造函数和原型是伪类理论的重要支撑工具。

一个对象的创建分为两步,第一步为new ,创建一个新对形象;第二步,新对象调用构造函数,并根据构造函数设置属性(方法可以看做函数属性)。比较特殊的是,所有的构造函数均有一个特殊的属性-prototype,该属性在函数被定义时就已经初始化为原型对象了。默认的,改原型对象有一个constructor属性,其值恰好为构造函数。添加给原型对象的任何属性,都会成为构造函数所初始化的对象的属性(通过属性值的查找完成继承)。

关于类的继承

(1)子类的构造函数的原型对象=父类的实例

(2)子类的构造函数=子类的构造函数

(3)删除父类构造函数所创建的属性。(不必要,重复的)

示例代码:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
<script src="myJs.js" type="text/javascript"></script>
</head>
<body>
<!--
<a href="javascript:void f(5);"> Open new window </a>
-->
<input type="button" onClick="javascript:var f = new outer(1); alert(f.inner1(2));">闭包1</input>
<br>
<input type="button" onClick="javascript:var f = new outer(2); f.x=1000; alert(f.inner2(3));">闭包2</input>
<br>
<input type="button" onClick="javascript:myClosure.x=1; alert(myClosure.x); var f = myClosure(1000); alert(f()); alert(f()); alert(f()); alert(f());">作用域与闭包</input>
<br>
<input type="button" onClick="javascript:var obj = {}; makeProperty(obj, 'Xxx'); obj.setXxx(100);alert(obj.getXxx());">闭包之保护变量避免外部访问</input>
<br>
<input type="button" onClick="javascript:var obj = {}; makeProperty2(obj, 'Xxx'); obj.setXxx(100);alert(obj.getXxx());">闭包之重名变量2</input>
<br>
<input type="button" onClick="javascript:var f = myClosure2(10); alert(f()); alert(f()); alert(f()); alert(f());">闭包里的this</input>
<br>
<input type="button" onClick="javascript:var f = new outer(2); f.x=1000; alert(outer.prototype.constructor);">构造函数的prototype.constructor</input>
<br>
<input type="button" onClick="javascript:var f = new outer(2); f.x=1000; alert(outer.prototype.prototype);">构造函数的prototype的prototype</input>
<br>
<input type="button" onClick="javascript:var f = new outer(2); f.x=1000; alert(f.prototype);">对象的prototype</input>
<br>
<input type="button" onClick="javascript:var f = new outer(2); f.x=1000; alert(f.constructor);">对象的constructor</input>
<br>
<input type="button" onClick="javascript:var f = new outer(2); f.x=1000; alert(f.inner1.prototype.constructor);">对象的方法prototype.constructor2</input>
<br>
<input type="button" onClick="javascript:alert(makefunc.prototype.constructor);">普通函数的prototype.constructor</input>
<br>
<input type="button" onClick="javascript:var f = makefunc(1); alert(f.prototype.constructor);">普通函数的prototype.constructor2</input>
</body>
</html>


JavaScript

/**
* Created with JetBrains WebStorm.
* User: hehe
* Date: 13-2-1
* Time: 上午10:48
* To change this template use File | Settings | File Templates.
*/

var abc = 1000;
/*
document.body.onload=function(){
document.write('this is a test<br>');
document.write(new Boolean());
}
*/

function f(x){
//print(x);
console.log(x);
arguments[0] = null;
//print(x);
console.log(x);
}

/*
alert(
function(x){
if(x<=1) return 1;
return x * arguments.callee(x-1)
}(5));
*/

var calculator = {
operand1:1,
operand2:1,
computer:function(){
this.result=this.operand1+this.operand2;
}
};

calculator.computer();
console.log(calculator.result);

function makefunc(x){
return function(){return x;}
}

function outer(x){
this.x = x;
}

outer.prototype.inner1 = function(y){
return this.x + y;
}

outer.prototype.inner2 = function(z){
return this.x+z;
}

function myClosure(initVal){
var x=initVal;
return function(){return x++;}
}

var def = 20;
function myClosure2(initVal){
var x=initVal + this.def;
var abc=1;
return function(){return x++ + this.abc;}
}

function makeProperty(o, name){
var x;
o["get"+name] = function(){return x;}
o["set"+name] = function(y){x=y;}
}

function makeProperty2(o, name){
var x;
o["get"+name] = function(){return x;}
o["set"+name] = function(x){x=x;}
}

function Rectangle(w,h){
this.width = w;
this.height = h;
}

Rectangle.prototype.area = function(){return this.width*this.height}

function PositionedRectangle(x,y,w,h){
Rectangle.call(this, w, h);
this.x = x;
this.y = y;
}

//alert(PositionedRectangle.prototype.constructor);

PositionedRectangle.prototype = new Rectangle();
delete PositionedRectangle.prototyp.width;
delete PositionedRectangle.prototyp.height;
PositionedRectangle.prototype.constructor = PositionedRectangle
PositionedRectangle.prototype.contains = function(x,y){
return (x >= this.x && x<= this.x + this.width && y >= this.y && y<= this.y + this.height);
}
//alert(PositionedRectangle.prototype.constructor);

function GenericToString(){}
GenericToString().prototype.toString = function(){

}


关于模块和命名空间

JavaScript本身是不支持模块和命名空间的。

命名空间巧妙地运用了Js对象的属性。

而模块一般多有两种定义方式(其实可以是任意的,只要不把全局命名空间搞乱了就行)。

一种比较优秀的定义模块和命名空间的方法是使用闭包。这有两个好处:一是内部调用可以不用写全称限定名;二是私有的辅助函数或者变量可以很好地隐藏,而只导出公共函数。

另一种为使用类。其实类也是一种特殊的函数-构造函数。

类的初始化方法一般也可分为两种。一为匿名函数定以后的立即调用,即function(){}();另一为构筑一模块的初始化句柄,并把此句柄注册于某个合适的监听器,比如onload。

学以致用,对于JQuery模块来说--JQuery应该算是一个模块了吧,$(JQuery,全局变量命名空间)符号应该是一个对象,$.xxx, $.fn.XXX即可说明。不过从$(selector)来看,$缺又像个函数名,函数在JavaScript里确实本身是一个对象,难道是函数对象?(个人理解哈,不知道对否?欢迎高人指正!)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: