JavaScript中使用原型实现继承

3
我有以下代码。为什么三个对象都指向同一个数组,而字符串变量是独立的?如何在不显式添加function B(){this.arr = [];}的情况下解决这个问题?

function A(){
  this.text = "";
  this.arr = [];

  this.action = function(){
    this.text+="z";
    this.arr.push(1); 
  }

  this.test = function(){
    console.log(this.text+"|"+this.arr);
  }
}

function B(){
    
}

B.prototype = new A();        
B.prototype.constructor = B;
var B1 = new B();
var B2 = new B();
var B3 = new B();

B1.action();
B2.action();
B3.action();
B1.test(); //z|1,1,1
B2.test(); //z|1,1,1
B3.test(); //z|1,1,1


你应该使用 function B() { A.call(this) } 而不是重复父构造函数所做的一切。 - Bergi
1个回答

0

一个解释是:

原型是对象之间的实时链接。因为B的原型是A的单一实例,所以数组prop是通过引用传递的。这意味着对于每个B实例,我们都可以访问原型上相同的A实例。这可能一开始听起来有点混乱,但这就是JavaScript中原型的魔力。

这是原型继承的一个警告。原型上的任何内容都将传递给每个实例。为了保持属性的不同实例,我们在构造函数中初始化对象的属性。

在JS中处理对象(如数组)时,它们是通过引用传递的。

要利用JS的原型系统,我建议像这样做:

function A(){
  this.text = "";

  this.action = function(){
    this.text+="z";
    this.arr.push(1); 
  }

  this.test = function(){
    console.log(this.text+"|"+this.arr);
  }
}

function B(){
    this.arr = [];
}

B.prototype = new A();

这样我们可以重用“父级”中的方法,并在“子级”中拥有本地化的数组。乍一看,这可能看起来像是一个经典的面向对象编程继承案例,但实际上有些不同。

如果您想了解更多关于JS原型的知识,我推荐阅读这篇文章

希望这能帮到您。


感谢您的解释。问题是,我还有C、D、E从A继承,我不想重复我的代码。我认为我必须使用寄生继承。https://dev59.com/P3I95IYBdhLWcg3w3yNU#2107586 - Ilya
不要使用这段代码。它仍然是错误的。 (https://dev59.com/AGQm5IYBdhLWcg3wug4u#17393153?Benefits-of-using-Object.create-for-inheritance) - Bergi
@Bergi 谢谢你提供的参考,我只是在解释为什么之前它没有起作用。我同意这不是实现原型继承的最佳方式。 - Andrei CACIO

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接