题记
每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,这个对象是包含可以由特定类型的所有实例共享的属性和方法。简单理解:prototype就是通过调用构造函数而创建的那个对象实例的原型对象,可以让所有对象实例共享它所包含的属性和方法。
javascript">function Person() {}
Person.prototype.name = "Helen";
Person.prototype.age = 23;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function () {
console.log(this.name);
};
var person1 = new Person();
person1.sayName(); // Helen
var person2 = new Person();
person2.sayName(); // Helen
上面这个例子中,我们把方法和属性添加到了Person的prototype属性中,所有构造函数的实例共享这些属性和方法。
理解原型对象
创建一个新函数,就会有一个prototype属性,指向函数的原型对象。默认情况下,所有原型对象都会自动获得一个constructor属性,指向prototype属性所在函数的指针,上述例子中的Person构造函数、Person的原型属性和Person现有的两个实例之间的关系可以用下图来表示:
注意:虽然person1和person2这两个实例都不包含属性和方法,但我们可以调用person1.sayName(),这是通过查找对象属性的过程来实现的。
每当代码读取某个对象的某个属性时,都会执行一次搜索,目标是具有给定名字的属性。搜索首先从对象实例本身开始,如果在实例中找到了具有给定名字的属性,则返回该属性的值;如果没有找到,则继续搜索指针指向的原型对象。
原型链引入
原型链是实现继承的主要方法,其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。从上面我们知道,每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。现在我们让原型对象等于另一个类型的实例,结果会是怎样呢?
此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针,假如另一个原型又是另一个类型的实例,那么上述关系依然成立,如此层层递进,就构成了实例与原型的链条,即原型链。
上图对应的代码如下:
javascript">function SuperType() {
this.property = true;
}
SuperType.prototype.getSuperValue = function() {
return this.property;
};
function SubType(){
this.subproperty = false;
}
// 继承了SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function() {
return this.subproperty;
};
var instance = new SubType();
alert(instance.getSuperValue())