基本对象分析
JavaScript中所有的东西都是对象,包括函数、字符、数字等等等。但是JavaScript没有Class这个概念。
JavaScript使用Function来模拟类,任何一个function都有一个对应的prototype对象来存储和扩展这个function的定义,也就是说原型对象是关联于函数的
我们计划使用new关键字来调用并生成新对象的函数,我们称为“构造函数”
一个基本的函数分析
function Car(){ color = 'red'; }; echo(Car); echo(Car.constructor); echo(Car.prototype); echo(Car.prototype.constructor);
输出结果
function Car() { color = "red"; }function Function() { [native code] }[object Object]function Car() { color = "red"; }
- Car本身是一个函数
- 它的constructor是原生对象(Native Function)
- 在函数Car定义解析的同时,会系统生成一个对象 Car.prototype,它将会是所有由Car生成(new)的实例对象的原型对象,注意它是对象,这不同于常见的Class概念。默认的原型对象没有任何属性
- Car的原型对象的Constructor就是Car自己,这也说明了原型对象是在函数定义的同时产生的。
原型对象
函数的原型对象是在脚本引擎解析每个函数代码时自动生成的,而不是执行时才生成
//function Car 是显式定义的,Car.prototype已经在代码解析时自动生成了,此时可以访问 echo(Car.prototype); function Car(){}; //function Plan 是赋值定义的,Plan.prototype没有自动生成了,此时不能访问 echo(Plan.prototype); Plan = function(){}; //现在才可以访问 echo(Plan.prototype);
原型对象实际的工作方式是一种链式查找,脚本运行时,脚本引擎首先在当前实例对象中查找指定的属性,如果有就直接使用,如果没有就到原型对象中找,如果原型对象也没有,就到原型对象的原型对象中查找,这是一个递归的查找链。所有的JavaScript对象的查找链最终都会归结到原生函数Object的原型对象中去。
function Car(){ this.color = 'red'; }; Car.prototype.color = 'blue'; Car.prototype.doors = 4; Object.prototype.wheels = 4; aCar = new Car; echo(aCar.color); echo(aCar.doors); echo(aCar.wheels);
输出结果:
red //注意:这里构造函数中定义的属性color覆盖了原型中的color定义4 //从原型中查找到了doors4 //从根原型中查找到了wheels
实例对象的原型对象关系链是有脚本引擎内部维护的,我们不能操作和修改它,但是可以通过定义和修改构造函数的prototype属性来影响的以后生成(new)的实例对象的原型对象,而JavaScript的继承关系正是通过这一方式来模拟的。
类的继承
JavaScript所有原生函数(Function,Array..)的Prototype对象指针是只读的,不能修改。你可以改变原型的内容,但不能改变原型对象本身。
而非原生函数的的原型对象是可以修改,如果把一个函数(A)的原型定义(prototype)指向另一个函数函数(B)的实例,这样可以就模拟出A继承B的效果
其实际效果是:把B的原型对象插入到了A的实例对象的原型链中去:
new A > A.prototype > B.prototype > …. > Object.prototype
//这样的代码是不能执行的 Array.prototype = new String(''); function Car(){} function RaceCar(){} //RaceCar 现在继承了 Car 的定义 RaceCar.prototype = new Car;
考虑到修改函数原型对象时可能会造成修改前的原型定义丢失,所有应该仅可能早的指定原型对象。
同时你也许需要修改新原型对象的constructor,使其指向当前构造函数,典型的继承关系处理代码如下:
function Car(){ Car.prototype.color = 'blue'; this.doors = 4; } function RaceCar(){ RaceCar.prototype.color = 'red'; this.doors = 2; } RaceCar.prototype = new Car; //RaceCar 现在继承了 Car 的定义 RaceCar.prototype.constructor = RaceCar; //修改constructor aCar = new RaceCar(); Car.prototype.wheels = 4; echo(aCar.color); echo(aCar.wheels);
输出结果为:
red4
11
建模结构图
我们使用一段代码及其对应的建模结构图来进一步说明JavaScript的继承处理方式:
代码:
function A(){ } B.prototype = new A; B.prototype.constructor = B; function B(){ }
结构图:
参考:http://mckoss.com/jscript/object.htm