尽管下面的实现看起来不错,因为它允许孩子拥有自己的成员副本(不具有修改父母自己的成员的能力),并且使用原型链,因此不会为每个对象实例创建属性,它效率不高,因为调用了Parent构造函数两次(一次执行apply和新的Parent实例化):
function Parent(a,b,c,d){
this.a = a;
this.b = b;
this.c = c;
this.d = d;
}
Parent.prototype.say_a = function(){
return this.a;
}
Parent.prototype.say_b = function(){
return this.b;
}
Parent.prototype.say_c = function(){
return this.c;
}
Parent.prototype.say_d = function(){
return this.d;
}
Parent.prototype.not_going_to_be_copied = function(){
console.log(“This function will not be recreated from one object instantiation to the next, making it very efficient.”);
}
function Child(a,b,c,d){
Parent.apply(this,arguments);
}
Child.prototype = new Parent();
c = new Child("a","b","c","d");
console.log([c.say_a(),c.say_b(),c.say_c(),c.say_d()].join(" "));
Javascript Patterns中的Stoyan提到了该替代方法,它根本不调用Parent构造函数:
Child.prototype = Parent.prototype;
但是,他说这样做的一个缺点是,如果继承链中某个地方的一个孩子或孙子修改了原型,它将影响所有父母和祖父母。
但是,我无法复制该主张:
function Parent(){}
Parent.prototype.set_a = function(a){
this.a = a;
}
Parent.prototype.get_a = function(){
return this.a;
}
function Child(){}
Child.prototype = Parent.prototype;
var c = new Child();
var p = new Parent();
c.set_a("a");
console.log(c.get_a()); // a
p.set_a("b");
console.log(p.get_a()); // b
console.log(c.get_a()); // a
c.prototype = {};
console.log("after mod " + c.get_a()); // after mod a
console.log("after mod " + p.get_a()); // after mod b
c.get_a = function(){return "am I changing parent?"}
console.log(c.get_a()); // am I changing parent?
console.log(p.get_a()); // b
如您所见,无论我如何修改Child的原型,它都不会影响Parent的原型。那我想念什么吗?孩子们对原型的修改会对父母产生影响吗?
后Child.prototype = Parent.prototype
的同一对象绑定到两个构造原型属性(和相当傻,IMOHO)。因此,对对象的修改称为,Child.prototype
也修改了Parent.prototype
所要求的“影响所有对象”,因为两个表达式都求值于同一对象。
考虑一下以后是否;
Child.prototype.hello = "Hello world"
// Noting that
Child.prototype === Parent.prototype // -> true, as per initial condition
然后;
var p = new Parent()
p.hello // -> "Hello world", showing the "affecting" behavior
因此可以看出,修改Child.prototype也会影响Parent实例的[prototype]-因为修改了同一对象。
但是,此问题并未得到重现,因为无法以这种方式“分配实例的原型”。也就是说,[prototype]链仅在创建新实例时根据构造函数的prototype属性设置(或通过Object.create设置)。分配给实例的prototype属性是..只是分配一个普通属性。
var c = new Child()
c.prototype = "Hello world"
typeof c.say_a // -> "function", didn't assign [prototype]
c.prototype // -> "Hello world"
c.__proto__ === Child.prototype // -> true, in browsers supporting __proto__
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句