1 对象相关的一些语言特性
1.1 一切皆为对象
JavaScript里所有的东西都是对象。 对象是属性的集合。 数字, 字符串, 布尔值等原始值是“伪对象”, 它们同样拥有属性, 但是是在栈上分配并按值传递。 而其他的对象是堆上分配并按引用传递。
一个很重要的概念是, 函数也是对象, 能够作为变量的值, 返回值, 参数或者属性的值。 函数对象特殊的地方是能通过“xxx()”语法执行包含在xxx函数对象内的代码。 因为这一特殊性, typeof xxx 将会返回function, 但这只是一种便利设施。
1.2 对象的属性可以动态添加和删除
以下为引用的内容: var foo = new Object(); |
1.3 除了宿主对象, 其它对象皆由构造函数创建
要有对象, 就先要有创建对象的方法。
在C++/Java等语言, 这个方法就是实例化XXX类的一个实例xxx.
而在JavaScript的世界里实际没有类的东西, 当然仍然可以用“类”和“实例”等惯用语来描述JavaScript中类似的行为, 但其机制是完全不同的。 JavaScript的对象是由构造函数创建的, 每个对象都有constructor属性表示创建该对象的构造函数:
以下为引用的内容: function Test() { this.a = "hello"; } |
构造函数也是对象, 那构造函数是由什么创建? 内建的Function函数:
以下为引用的内容: function Test(a, b) |
Function函数又是由什么创建? 实际上Function是本机代码实现的固有对象. 不过为了一致性, Function也有constructor属性, 该属性指向它自己. 接上面的代码:
以下为引用的内容: /* 输出 function Function(){ |
2 原型prototype
2.1 prototype的概念
prototype是构造函数的一个属性, 该属性指向一个对象。 而这个对象将作为该构造函数所创建的所有实例的基引用(base reference), 可以把对象的基引用想像成一个自动创建的隐藏属性。 当访问对象的一个属性时, 首先查找对象本身, 找到则返回; 若不, 则查找基引用指向的对象的属性(如果还找不到实际上还会沿着原型链向上查找, 直至到根)。 只要没有被覆盖的话, 对象原型的属性就能在所有的实例中找到。
原型默认为Object的新实例, 由于仍是对象, 故可以给该对象添加新的属性:
以下为引用的内容: // prototype默认为new Object(); 为了方便, 记为p_obj |
2.2 原型链
除了能修改prototype指向的对象, 还能修改prototype指向哪一个对象, 即为prototype赋予一个不同的对象。 这可以实现一种简单的继承:
以下为引用的内容: function Superman() {} |
如果先实例化出一个对象, 再为构造函数prototype赋予一个不同的对象, 将会: 已经创建的对象的基引用不变, 将来创建的对象的基引用为新的原型对象:
以下为引用的内容: var f1 = {echo: function() { alert("sound"); } }; |
所有的构造函数的prototype都不能为空, 就是说Superman.prototype = null 会被解释引擎无视; 另一方面, Object构造函数也有prototype属性(该属性是只读的, 可以为原型增加属性,但不能赋予不同的对象), 故因此可以有多层的原型链, 但原型链的根必定会是Object.prototype 。 这意味着给Object.prototype增加属性影响到所有对象:
以下为引用的内容: Object.prototype.echo = function() { |
3. 构造函数和new的实质
构造函数是一个地地道道的函数, 一个函数之所以能成为构造函数, 是因为new运算符:
以下为引用的内容: this.msg = "window"; |
二者区别在于如何切入对象: Test() 在某个对象(例子中为window)的上下文上执行代码, 即this指向这个对象; new Test()创建一个新对象, 并以这个新的对象为上下文(this指向新对象)执行代码, 然后返回这个新对象。
假如有个函数:
以下为引用的内容: function Test() { |
结合以上的所有论述, 可以推测new Test()行为的伪代码表示为:
以下为引用的内容: 创建一个新对象temp; |
原文地址:http://www.cnblogs.com/FlyingCat/archive/2009/09/21/1570656.html
如对本文有疑问,请提交到交流论坛,广大热心网友会为你解答!! 点击进入论坛