-1

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

3
  • 1
    That's because numbers is not on the prototype. You are using an instance variable in A and thats carrying through with new B instances Commented Nov 15, 2013 at 16:18
  • So there are no realy "private" properties in JavaScript? Is the solution to replace var numbers with this.numbers = [];? Commented Nov 15, 2013 at 16:20
  • 1
    Ya there's no way to do inheritence with private variables. You can add this to the B constructor to A.apply(this, arguments) and I think your code will work Commented Nov 15, 2013 at 16:23

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

B.prototype = Object.create(A.prototype); and A.call(this) does the trick! Thanks!
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.