Javascript中的继承机制是所谓的原型对象继承,通过属性访问机制的特殊性来实现继承的。之前我一直以为所有对象的原型对象就是prototype所指的那个对象。后来在看javascript设计模式的时候发现作者注中有一句话与我之前的理解不同,他说“每个对象都有一个原型对象,但这并不意味着每个对象都有一个prototype属性”。看完我就有点迷茫了,决定彻底把这个死人的原型继承搞搞清楚。然后翻了些文章和书籍,最后终于在javascript权威指南第五版中找到了个人 认为比较权威的解释。关于原型链和属性访问机制我就不再阐述了,这方面可以看看Rocky的文章 写的蛮清楚的 http://blog.csdn.net/rocky_j2ee/archive/2009/03/21/4012385.aspx
那我们先从创建对象说起,用new操作符创建对象的时候javascript会做3件事:
首先是创建一个空对象(empty object),
然后对这个空对象的原型对象进行赋值,
最后把这个空对象赋值给构造函数的this属性且运行这个构造函数。
function Person(name) {
this.name = name;
}
var p = new Person(); 相当于以下步骤:
1. Var p = {};
2. p.[[prototype]] = Person.prototype //这一步是伪代码,实际上一个对象的原型对象是不能通过代码来访问的,
//这里只是为了说明创建对象的步骤
3. p.methodName = Person ; //这样的话Person的this就会指向p
p.methodName();
如果你对第二步不是很明白,那么先把代码放一放,接下来我会详细解释下第二步原型对象的赋值(或者说构造函数和原型对象的关系):上面我提到过在创建完一个空对象后,会初始化这个空对象的原型对象,javascript会把构造函数的一个叫做prototype的属性所指向的对象赋值给当前空对象的原型对象。所有的function都有一个prototype属性,当一个function被定义之后这个属性会被自动的创建和初始化。一个function 的prototype属性的初始值是一个对象(an object),这个对象只有一个属性叫做constructor,而这个constructor 的值就是当前这个函数(或者叫构造函数)。
function Person(name) {
this.name = name;
}
Person === Person.prototype.constructor; //true
所以你对构造函数的prototype属性进行操作:譬如添加属性或方法,又或者重新赋值,都会反映在用这个构造函数创建出来的对象上。对prototype添加方法或属性,所创建的对象也会继承这些方法和属性,重新赋值的话所创建的对象就会继承新的prototype的方法和属性。
接下来总结下一个容易让人误解的提法和一些比较绕人的题目:
1. 所有的对象都有原型对象,但不是每个对象都有prototype属性。
2. prototype属性是函数(function)特有的属性。
3.函数(function)也是一个对象,那么它也有原型对象,它的原型对象和它的prototype属性没有任何关系。
4.一个函数的原型对象是Function.prototype所指向的那个对象。因为所有的function都是Function的实例,Function是所有funciton的构造函数,按照上面的定义,一个对象的原型对象是这个对象的构造函数的prototype所指的那个对象。
function Person(name) {
this.name = name;
}
var p = new Person(“Marry”);
p 的原型对象是Person.prototype
Person 的原型对象是Function.prototype
Person.prototype.constructor === Person //true
最后让我们来看下那些经典的继承的例子:
function Person(name){
this.name = name;
}
Person.prototype.walk = function () {
alert(“walking”);
}
function Author(){
}
现在有了Author,想要用Author创建出来的对象继承Person那么就把Author的prototype属性重新赋值为一个Person对象
Author.prototype = new Person();
然后赋值之后原来的Author.prototype.constructor 就不是原来的Author 所以还要
Author.prototype.construtor = Author
以上两部就是最最基本的原型继承,其他一些涉及到模拟基于类继承中涉及到的superclass不在这篇文章讨论原意范围内。
自己在 javascript原型继承上也绕了好久一直是一知半解,希望这篇文章对大家有帮助^_^