js的面向对象不像JAVA一样这么严谨,原型链也很难理解。这里就用我理解的语言形式来解释下。
比如现在有一个叫做DOG的构造函数,表示狗对象的原型,相当于java里面的构造函数
function DOG(name){
this.name = name; //this指向的是这个对象实例,name是公有属性
}
对这个构造函数使用new,就会生成一个狗对象的实例。
var dogA = new DOG('大毛');
alert(dogA.name); // 大毛
每一个实例对象,都有自己的属性和方法的副本。比如你new了两个狗对象,里面的name就有两份,相互之间不影响。这不仅无法做到数据共享,也是极大的资源浪费。
prototype属性的引入
这个属性包含一个对象(以下简称”prototype对象”),所有实例对象需要共享的属性和方法,都放在这个对象里面;那些不需要共享的属性和方法,就放在构造函数里面
还是以DOG构造函数为例,现在用prototype属性进行改写:
function DOG(name){
this.name = name;
}
DOG.prototype = { species : '犬科' };
var dogA = new DOG('大毛');
var dogB = new DOG('二毛');
alert(dogA.species); // 犬科
alert(dogB.species); // 犬科
现在,species属性放在prototype对象里,是两个实例对象共享的。只要修改了prototype对象,就会同时影响到两个实例对象。这个就相当于java中的静态属性,所有的实例都是共享的,而且只能用对象来改,不能用实例来改。
现在,species属性放在prototype对象里,是两个实例对象共享的。只要修改了prototype对象,就会同时影响到两个实例对象。
DOG.prototype.species = '猫科';
alert(dogA.species); // 猫科
alert(dogB.species); // 猫科
下面正式来解释原型链的概念
正是因为有了prototype对象,我们把这个有prototype串起来的直到Object.prototype.prototype为null的链叫做原型链。
var Person = function () {
};
Person.prototype.Say = function () {
alert("Person say");
}
Person.prototype.Salary = 50000;
var Programmer = function () {
};
Programmer.prototype = new Person();
Programmer.prototype.WriteCode = function () {
alert("programmer writes code");
};
Programmer.prototype.Salary = 500;
var p = new Programmer();
/*
*在执行p.Say()时,先通过p._proto_找到Programmer.prototype
* 然而并没有Say方法,继续沿着Programmer.prototype._proto_ 找到Person.prototype,ok 此对象下有Say方法 执行之
*/
p.Say();
p.WriteCode(); //同理 在向上找到Programmer.prototype时 找到WriteCode方法 执行之