Javascript类的原型对象和继承
基本对象分析
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

最近评论