核心提示:原型链的基本思想:就是利用原型让一个引用类型继承另一个引用类型的属性和方法,每个构造函数都有一个原型对象(prototype),同时原型对象都包含一个指向构造函数的指针(constructor),而实...
原型链的基本思想:就是利用原型让一个引用类型继承另一个引用类型的属性和方法,
每个构造函数都有一个原型对象(prototype),同时原型对象都包含一个指向构造函数的指针(constructor),而实例都包含一个指向原型对象内部的指针([[Prototype]])此指针指向原型而不指向构造函数。
让原型对象等于另一个类的实例,即该原型对象包含一个指向另一个构造函数的指针另一个构造函数的实例包含一个指向该原型对象的指针,如果让第三个原型对象等于第二个类的实例。。。以此叠加下去,就构成了原型链
ps:ECMAScript 5增加了一个新方法,叫Object.getPrototypeOf(),在所有支持的实现中,这个方法返回[[PrototypeJ]]的值;
Object.getPrototypeOf(s) //s为Second是对象,看后面代码
话不多说先贴代码:(内附有详细注释,详看)
function First(){
this.name = "snake";
}
First.prototype = {
name1 : "snake1"
};
function Second(){
this.sex = "男";
}
Second.prototype = {
sex1 : "男1"
};
function Third(){
this.age = 19;
}
Third.prototype = {
age1 : 191
};
console.log("继承前: ");
console.log(Second.prototype); // { sex1: '男1' }
console.log("++++++++++++++++++++++++");
Second.prototype = new First(); // Second原型指向First实例,本质就是重写原型
var s = new Second();
Second.prototype.sex2 = "男2";
//对象自变量方法创建原型相当于把原型重写,会覆盖之前的原型属性
// Second.prototype = {
// sex2 : "男2"
// };
console.log("继承后: ");
console.log(Second.prototype); // { name: 'snake', sex2: '男2' }
console.log("s.name: "+s.name); // s.name: snake 继承自构造函数的属性
console.log("s.name1: "+s.name1); // s.name1: snake1 继承自原型的属性
console.log("s.sex: "+s.sex); // s.sex: 男
console.log("s.sex1: "+s.sex1); // s.sex1: undefined 最初定义的原型已被重写,无法访问
console.log("s.sex2: "+s.sex2); // s.sex2: 男2 重写原型,即继承后添加的原型属性
console.log("____________________")
Third.prototype = new Second();
var t = new Third();
console.log("t.name: "+t.name); // t.name: snake 继承自Second,Second继承自First是name属性
console.log("t.sex: "+t.sex); // t.sex: 男 继承自Second构造函数的属性
console.log("t.sex2: "+t.sex2); // t.sex2: 男2 继承自Second原型的属性
console.log("t.age: "+t.age); // t.age: 19 自身属性
由上述代码可以明显的看出当Second的原型对象等于First的实例时,实现了Second对First的继承,而此继承所实现的本质就是原型对象的重写(可以看出当
Second.prototype = new First();
执行后,Second原有的原型属性被覆盖无法访问
)与此同时Second的对象s具有了First实例的所有属性,Third对象在继承Second的同时同样继承了Second继承自First的属性
ps:通过原型链实现继承时,不能使用对象自变量创建原型方法,使用对象自变量相当于重写原型会覆盖前面定义以及继承的属性


