JavaScript学习小结(二)
-
关于JavaScript的版本
目前Js标准有两个支撑,分别为ECMA-262和ECMA-357.357是针对262的一个XML扩展。
-
关于JavaScript的运行环境
只要有解释器,客户端/服务器端均可。由于浏览器默认装载了解释器,所以通过浏览器学习Js是很方便的。
- 关于JavaScript的类型变换
基本数据类型之间,对象和基本数据类型是可以自动转换的。
基本数据类型->对象的转换,涉及到一个概念--瞬态对象。所谓的瞬态,是指被系统临时创建用后就丢弃的。
如下代码即为瞬态对象的典型例子。
1 var s = 'abc'; 2 console.log(s.length);
var s = 'abc'; console.log(s.length);
至于对象->基本数据类型的转换,则可能涉及到对象的toString,valueOf方法。
- 关于传值和传址
基本数据类型:传值
函数和数组:传址。关于这一点还是和传统Java有区别的,JavaScript中更像是引用的传值。以下的代码较好地解释了这一点。
1 // This is another version of the add_to_totals() function. It doesn't 2 // work, though, because instead of changing the array itself, it tries to 3 // change the reference to the array. 4 function add_to_totals2(totals, x) 5 { 6 newtotals = new Array(3); 7 newtotals[0] = totals[0] + x; 8 newtotals[1] = totals[1] + x; 9 newtotals[2] = totals[2] + x; 10 totals = newtotals; // This line has no effect outside of the function 11 }
字符串:比较特殊,可以认为是传值。这一点和Java不同,值得注意。
- 关于变量的重复声明
对变量没有任何影响。
- 关于未定义的变量
未声明的变量不能直接读,否则会发生错误;但却可以直接赋值,赋值的过程中系统隐式声明它。
- 关于变量的作用域
全局变量就是全局对象的属性,局部变量就是调用对象的属性。调用对象和全局对象共同构成了作用域链(Scope chain)。变量名解析(variable name resolution)就是在这个作用域链中查询变量的过程。按照我的理解,局部变量所在的调用对象实际上和函数相关,它是指函数被调用时创建的。该调用对象的一个属性被初始化成一个名叫 arguments 的属性,它引用了这个函数的 Arguments 对象--函数的实际参数。所有用 var 语句声明的本地变量也被定义在这个调用对象里。这个时候,调用对象处在作用域链的头部,本地变量、函数形式参数和 Arguments 对象全部都在这个函数的范围里了。其实,由于JavaScript是通过词法来划分作用域的,当一个函数在定义的时候,其作用域链就形成了,并成为该函数的内部状态。只不过当调用的时候,所创建的调用对象被添加到定义时创建的作用域链的头部。
- 关于闭包
代码和作用域的综合体叫做闭包。所有的JavaScript函数都是闭包。
只有当一个嵌套函数被到处到它所定义的作用域外时,这种闭包才是有趣的。--摘自犀牛书
- 关于类,构造函数和原型
JavaScript还不支持真正的类,其所为的类为伪类(pseudoclass)。构造函数和原型是伪类理论的重要支撑工具。
一个对象的创建分为两步,第一步为new ,创建一个新对形象;第二步,新对象调用构造函数,并根据构造函数设置属性(方法可以看做函数属性)。比较特殊的是,所有的构造函数均有一个特殊的属性-prototype,该属性在函数被定义时就已经初始化为原型对象了。默认的,改原型对象有一个constructor属性,其值恰好为构造函数。添加给原型对象的任何属性,都会成为构造函数所初始化的对象的属性(通过属性值的查找完成继承)。
- 关于类的继承
(1)子类的构造函数的原型对象=父类的实例
(2)子类的构造函数=子类的构造函数
(3)删除父类构造函数所创建的属性。(不必要,重复的)
示例代码:
1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 2 "http://www.w3.org/TR/html4/loose.dtd"> 3 <html> 4 <head> 5 <title></title> 6 <script src="myJs.js" type="text/javascript"></script> 7 </head> 8 <body> 9 <!-- 10 <a href="javascript:void f(5);"> Open new window </a> 11 --> 12 <input type="button" onClick="javascript:var f = new outer(1); alert(f.inner1(2));">闭包1</input> 13 <br> 14 <input type="button" onClick="javascript:var f = new outer(2); f.x=1000; alert(f.inner2(3));">闭包2</input> 15 <br> 16 <input type="button" onClick="javascript:myClosure.x=1; alert(myClosure.x); var f = myClosure(1000); alert(f()); alert(f()); alert(f()); alert(f());">作用域与闭包</input> 17 <br> 18 <input type="button" onClick="javascript:var obj = {}; makeProperty(obj, 'Xxx'); obj.setXxx(100);alert(obj.getXxx());">闭包之保护变量避免外部访问</input> 19 <br> 20 <input type="button" onClick="javascript:var obj = {}; makeProperty2(obj, 'Xxx'); obj.setXxx(100);alert(obj.getXxx());">闭包之重名变量2</input> 21 <br> 22 <input type="button" onClick="javascript:var f = myClosure2(10); alert(f()); alert(f()); alert(f()); alert(f());">闭包里的this</input> 23 <br> 24 <input type="button" onClick="javascript:var f = new outer(2); f.x=1000; alert(outer.prototype.constructor);">构造函数的prototype.constructor</input> 25 <br> 26 <input type="button" onClick="javascript:var f = new outer(2); f.x=1000; alert(outer.prototype.prototype);">构造函数的prototype的prototype</input> 27 <br> 28 <input type="button" onClick="javascript:var f = new outer(2); f.x=1000; alert(f.prototype);">对象的prototype</input> 29 <br> 30 <input type="button" onClick="javascript:var f = new outer(2); f.x=1000; alert(f.constructor);">对象的constructor</input> 31 <br> 32 <input type="button" onClick="javascript:var f = new outer(2); f.x=1000; alert(f.inner1.prototype.constructor);">对象的方法prototype.constructor2</input> 33 <br> 34 <input type="button" onClick="javascript:alert(makefunc.prototype.constructor);">普通函数的prototype.constructor</input> 35 <br> 36 <input type="button" onClick="javascript:var f = makefunc(1); alert(f.prototype.constructor);">普通函数的prototype.constructor2</input> 37 </body> 38 </html>
JavaScript
1 /** 2 * Created with JetBrains WebStorm. 3 * User: hehe 4 * Date: 13-2-1 5 * Time: 上午10:48 6 * To change this template use File | Settings | File Templates. 7 */ 8 9 var abc = 1000; 10 /* 11 document.body.onload=function(){ 12 document.write('this is a test<br>'); 13 document.write(new Boolean()); 14 } 15 */ 16 17 function f(x){ 18 //print(x); 19 console.log(x); 20 arguments[0] = null; 21 //print(x); 22 console.log(x); 23 } 24 25 /* 26 alert( 27 function(x){ 28 if(x<=1) return 1; 29 return x * arguments.callee(x-1) 30 }(5)); 31 */ 32 33 var calculator = { 34 operand1:1, 35 operand2:1, 36 computer:function(){ 37 this.result=this.operand1+this.operand2; 38 } 39 }; 40 41 calculator.computer(); 42 console.log(calculator.result); 43 44 function makefunc(x){ 45 return function(){return x;} 46 } 47 48 function outer(x){ 49 this.x = x; 50 } 51 52 outer.prototype.inner1 = function(y){ 53 return this.x + y; 54 } 55 56 outer.prototype.inner2 = function(z){ 57 return this.x+z; 58 } 59 60 function myClosure(initVal){ 61 var x=initVal; 62 return function(){return x++;} 63 } 64 65 var def = 20; 66 function myClosure2(initVal){ 67 var x=initVal + this.def; 68 var abc=1; 69 return function(){return x++ + this.abc;} 70 } 71 72 function makeProperty(o, name){ 73 var x; 74 o["get"+name] = function(){return x;} 75 o["set"+name] = function(y){x=y;} 76 } 77 78 function makeProperty2(o, name){ 79 var x; 80 o["get"+name] = function(){return x;} 81 o["set"+name] = function(x){x=x;} 82 } 83 84 function Rectangle(w,h){ 85 this.width = w; 86 this.height = h; 87 } 88 89 Rectangle.prototype.area = function(){return this.width*this.height} 90 91 function PositionedRectangle(x,y,w,h){ 92 Rectangle.call(this, w, h); 93 this.x = x; 94 this.y = y; 95 } 96 97 //alert(PositionedRectangle.prototype.constructor); 98 99 PositionedRectangle.prototype = new Rectangle(); 100 delete PositionedRectangle.prototyp.width; 101 delete PositionedRectangle.prototyp.height; 102 PositionedRectangle.prototype.constructor = PositionedRectangle 103 PositionedRectangle.prototype.contains = function(x,y){ 104 return (x >= this.x && x<= this.x + this.width && y >= this.y && y<= this.y + this.height); 105 } 106 //alert(PositionedRectangle.prototype.constructor); 107 108 function GenericToString(){} 109 GenericToString().prototype.toString = function(){ 110 111 }
- 关于模块和命名空间
JavaScript本身是不支持模块和命名空间的。
命名空间巧妙地运用了Js对象的属性。
而模块一般多有两种定义方式(其实可以是任意的,只要不把全局命名空间搞乱了就行)。
一种比较优秀的定义模块和命名空间的方法是使用闭包。这有两个好处:一是内部调用可以不用写全称限定名;二是私有的辅助函数或者变量可以很好地隐藏,而只导出公共函数。
另一种为使用类。其实类也是一种特殊的函数-构造函数。
类的初始化方法一般也可分为两种。一为匿名函数定以后的立即调用,即function(){}();另一为构筑一模块的初始化句柄,并把此句柄注册于某个合适的监听器,比如onload。
学以致用,对于JQuery模块来说--JQuery应该算是一个模块了吧,$(JQuery,全局变量命名空间)符号应该是一个对象,$.xxx, $.fn.XXX即可说明。不过从$(selector)来看,$缺又像个函数名,函数在JavaScript里确实本身是一个对象,难道是函数对象?(个人理解哈,不知道对否?欢迎高人指正!)。
浙公网安备 33010602011771号