简体   繁体   English

修改孩子的原型会影响父母的原型吗?

[英]Can modifying the prototype on a child affect the parent's prototype?

While this below implementation seems good, because it allows a child to have its own copy of own members (without having ability to modify parent's own members), plus it uses the prototype chain, so properties won't be recreated for each object instantiation, it is not efficient because the Parent constructor is invoked twice (once for apply and new Parent instantiation): 尽管这种下面的实现看起来不错,因为它允许子代拥有自己的成员副本(不具有修改父代成员的能力),并且使用原型链,因此不会为每个对象实例创建属性,它效率不高,因为调用了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(" "));

Stoyan in Javascript Patterns mentions this alternative, which does not invoke Parent constructor at all: Javascript Patterns中的Stoyan提到了该替代方法,它根本不调用Parent构造函数:

Child.prototype = Parent.prototype;

However, he says a drawback to this is if one child or grandchild somewhere down the inheritance chain modifies the prototype, it affects all parents and grandparents. 但是,他说这样做的缺点是,如果继承链中某个地方的一个孩子或孙子修改了原型,它将影响所有父母和祖父母。

However, I cannot reproduce that claim: 但是,我无法复制该主张:

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

As you can see, no matter how I modify the prototype of Child, it does not affect the prototype of Parent. 如您所见,无论我如何修改Child的原型,它都不会影响Parent的原型。 So am I missing something? 那我想念什么吗? Can the children's modification of prototype have affect on the Parent? 孩子们对原型的修改会对父母产生影响吗?

After Child.prototype = Parent.prototype the same object is bound to both constructors' prototype property (and is fairly silly, IMOHO). Child.prototype = Parent.prototype同一对象绑定到两个构造函数的原型属性(并且相当愚蠢,IMOHO)。 Thus modifying the object known as Child.prototype also modifies Parent.prototype which "affects all" as claimed because both expressions evaluate to the same object . 因此,修改被称为Child.prototype的对象将修改Parent.prototype ,如所声明的那样“影响所有对象”,因为两个表达式求值的对象都是相同的

Consider if later on; 考虑一下以后是否;

Child.prototype.hello = "Hello world"
// Noting that
Child.prototype === Parent.prototype  // -> true, as per initial condition

Then; 然后;

var p = new Parent()
p.hello                  // -> "Hello world", showing the "affecting" behavior    

So it can be see that modifying Child.prototype affected the [prototype] of instances of Parent as well - because the same object was modified. 因此可以看出,修改Child.prototype也会影响Parent实例的[prototype]-因为修改了同一对象

However, the issue isn't being reproduced because one cannot "assign the prototype of an instance" in such a manner. 但是,此问题并未得到重现,因为无法以这种方式“分配实例的原型”。 That is, the [prototype] chain is only set based of the constructor's prototype property (or via Object.create), at time of creating a new instance. 也就是说,[prototype]链在创建新实例时根据构造函数的 prototype属性设置(或通过Object.create设置)。 Assigning to the prototype property of an instance is .. just assigning a normal property. 分配给实例的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__
Child.prototype = Parent.prototype;

Is bad because if Child is a Dog and Parent is Animal we can say a Dog is an Animal but we can't say an Animal is a Dog (what about a Snake?). 不好是因为如果孩子是狗,父母是动物,我们可以说狗是动物,但不能说动物是狗(蛇是什么?)。

Here is where it goes wrong 这是哪里出了问题

var Animal=function(){};
var Snake = function(){};
Snake.prototype=Animal.prototype;
var Dog = function(){};
Dog.prototype=Animal.prototype;
Dog.prototype.bark=function(){console.log('I am barking');};

var aSnake = new Snake();
aSnake.bark();//I am barking ???

It's better to use Object.crate to set prototype of Child instead of setting it to an instance of Parent because Parent has instance specific members that should not be on Child and you may have a situation where Parent constructor needs parameters passed that are not available when declaring the Child type (and it's just bad form). 最好使用Object.crate来设置Child的原型,而不是将其设置为Parent的实例,因为Parent具有实例特定的成员,这些成员不应该位于Child上,并且您可能会遇到以下情况:Parent构造函数需要传递在以下情况下不可用的参数:声明Child类型(这是错误的形式)。

In your code c.get_a is shadowing the prototype member and does not affect the prototype. 在您的代码中c.get_a隐藏了原型成员,并且不影响原型。 This is explained in detail here . 这将在此处详细说明。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM