JavaScript inheritance with unexpected behaviour

会有一股神秘感。 提交于 2019-12-13 21:15:29

问题


I don't know how to solve the following JavaScript problem:

function A() {
    var numbers = [];

    this.addNumber = function(number) {
        numbers.push(number);
    }

    this.getNumbers = function() {
        return numbers;
    }
}

A.prototype.alertNumbers = function() {
    var numbers = this.getNumbers();
    var length = numbers.length;
    var number;
    var numbersString = "";
    for (var i = 0; i < length; i++) {
        number = numbers[i];
        numbersString += " " + number;
    }
    alert(numbersString);
}

B.prototype = new A();

function B() {
    this.addNumber(1);
    this.addNumber(2);
}

var b = new B();
b.alertNumbers();

var otherB = new B();
otherB.alertNumbers();

The working code is here: http://jsfiddle.net/pFxse/

I'm expecting that otherB.alertNumbers(); also shows "1 2" and not "1 2 1 2".

Thanks


回答1:


The problem is that when you do:

B.prototype = new A();

You set B.prototype to be an instance of A, thus B.prototype will have 2 functions that access a private variable numbers.

Now when you access (new B()).addNumber(), you will use the function from the prototype and thus the array from the prototype. All instances will use that array. All instances will push to that array.

To fix it it is enough to do:

function B() {
    A.call(this); // call superclass
    this.addNumber(1);
    this.addNumber(2);
}

By calling the superclass in B's constructor, you have created a numbers variable for each instance of B, along with 2 functions which enclose over that variable. Each instance will use its specific addNumbers function which uses its specific closured array.


Since you already did that, your inheritance scheme can be simplified as well:

B.prototype = Object.create(A.prototype);

Instead of creating a new object of type A and setting that to the prototype of B, you set the prototype of B to inherit directly from the prototype of A. You still have methods defined in A's constructor because you called the superclass. The advantage is that now you no longer create instances of A for each subclass and (perhaps more important) you can now pass arguments to the constructor:

function A(name) {
  this.name = name;
}

function B(name) {
  A.call(this, 'B' + name);
}
B.prototype = Object.create(A.prototype);

You can't have this scenario in your inheritance model.




回答2:


You've got one "A" instance, and it's the prototype for the "B" constructor. Thus, each "B" instance shares that same closure variable in the "A" instance.



来源:https://stackoverflow.com/questions/20005474/javascript-inheritance-with-unexpected-behaviour

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!