您的位置:首页 > 其它

解决原型链的引用类型值问题 --- 组合继承

2013-05-21 20:32 169 查看
首先声明一个概念:我们虽然可以通过实例访问保存在原型中的值,但却不能通过实例重写原型中的值。如果我们在实例中给一个属性赋值,而且该属性与原型中的一个属性同名,那我们就在实例中创建该属性,该属性会屏蔽原型中的那个属性。

但是,虽然不能重写原型中的值,如果原型中包含有引用类型(数组,对象)的值的话,我们可以通过引用来修改原型中的值。

function Cat(){

};
Cat.prototype.type="Animal";
Cat.prototype.friends=['kitty','cookie'];
Cat.prototype.speak=function(){
console.log("喵");
}
var cat1=new Cat();
var cat2=new Cat();

cat1.friends.push('apple');

console.log(cat2.friends);
console.log(cat1.type);
console.log(cat2.type);
cat1.speak();
cat2.speak();


原型中有一个共享的数组属性friends,每一个继承它的实例都可以对它进行修改。显然,每只猫咪都有应该自己的friends,而且不应该决定其他猫咪该有什么friends。好吧,为了猫咪们能够和谐相处,我们做一点点的改进。

//最常用的创建自定义类型的方法

function Cat(){
this.friends=['kitty','cookie'];
};
Cat.prototype.type="Animal";
Cat.prototype.speak=function(){
console.log("喵");
}
var cat1=new Cat();
var cat2=new Cat();

cat1.friends.push('apple');

console.log(cat2.friends);
console.log(cat1.type);
console.log(cat2.type);
cat1.speak();
cat2.speak();


构造函数为每只猫咪创建自己的friends属性,也就是说,把需要共享的属性和方法放在prototype里,而实例自己独立的属性,则放在构造函数里。

在原型链中,由于实例是另一个实例的原型对象这样的关系,我们即使把独立属性放在构造函数里,这个属性最终还是会成为另一个实例的原型里的属性,上面的问题又重演了,怎么办。先举个原型链的例子

function Sub(){

};

function Super(){
this.friends=['Tom','Jack'];
}

Sub.prototype=new Father();
Super.prototype.species="human";

var instance1=new Sub();
var instance2=new Sub();
instance1.friends.push('danyan');
console.log(instance1.friends);//['Tom','Jack','danyan']
console.log(instance2.friends);//['Tom','Jack','danyan']


Super的独立属性被写在构造函数里了,它的实例都将拥有不同的friends属性,但是,他的实例成了Sub的原型,Sub的实例,又将共享friends属性,怎么破。

分析一下,我们的目的是要Sub继承Super,而且Super中引用类型的属性不被Sub的实例共享。我们能不能像解决猫咪的问题那样,把这个引用类型的应该被独立出来的属性,放在Sub的构造函数里,让Sub的实例们各自生成自己的这个属性。答案,yes

//最常用的继承模式

function Sub(){
Super.apply(this,arguments);
};

function Super(){
this.friends=['Tom','Jack'];
}

Sub.prototype=new Father();
Super.prototype.species="human";

var instance1=new Sub();
var instance2=new Sub();
instance1.friends.push('danyan');
console.log(instance1.friends);//['Tom','Jack','danyan']
console.log(instance2.friends);//['Tom','Tack']


如此一来,在调用Sub生成实例时,运行了Super函数(super在这里被当成一个普通的函数),为实例生成了各自的friends属性,屏蔽了Sub的原型即Super的实例中的friends属性。这种方法被称为组合继承。组合了经典继承(像sub那样借用super)和原型链继承。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐