Arrays and Objects In Prototypes - Not Treated as References

I have a prototype object in Javascript, when I initialise a new instance of the prototype and update properties in the prototype, it updates for all elements. I understand that arrays and objects are passed by reference and was wondering of a solution that would get you around this?

let Test = function () {}

Test.prototype = {
    array: [],
    add: function (value) {
        this.array.push(value)
    }
}

let test1 = new Test();
let test2 = new Test();

test1.add(1);
test1.add(2);

// Prints [1, 2]
console.log(test2.array);

One solution would be:

class Test {

    constructor() {
        this.array = []
    }

    add(value) {
        this.array.push(value)
    }
}

let test1 = new Test();
let test2 = new Test();

test1.add(1);
test1.add(2);

// Prints []
console.log(test2.array);

But I am not looking for an ES6 Approach, something more "native" javascript.

Thanks for the help!

Answers:

Answer

That's the thing: they are treated as references.

When you do this:

Test.prototype = {
    array: [], // <- This creates a new array and it's being used in all instances
    add: function (value) {
        this.array.push(value)
    }
}

What you want is getting different array instances for different class instances. In that case, simply do this.array = [] in your constructor:

let Test = function () { this.array = []; }

let Test = function () { this.array = []; }

Test.prototype = {
    array: [],
    add: function (value) {
        this.array.push(value)
    }
}

let test1 = new Test();
let test2 = new Test();

test1.add(1);
test1.add(2);

console.log(test1.array);
// => [1, 2]

console.log(test2.array);
// => []

Answer

Initialize mutable members in the constructor, not in the prototype. If it's in the prototype, it will be shared between all instances:

let Test = function () {
    this.array = [];
}

Test.prototype = {
    add: function (value) {
        this.array.push(value)
    }
}

let test1 = new Test();
let test2 = new Test();

test1.add(1);
test1.add(2);

console.log(test1.array);
console.log(test2.array);

Answer

Define the array on the instance instead of on the prototype:

function Test() {
    this.array = [];
}

Test.prototype.add = function (value) {
    this.array.push(value)
}
Answer

I understand that arrays and objects are passed by reference

No, they are not. But they're referenced by object references, which is an entirely different thing,1 and is indeed the issue you're running into.

and was wondering of a solution that would get you around this?

Do exactly what you did in the ES6 approach: Put it on the object itself, not the prototype:

let Test = function () {
    this.array = [];
};

1 (All that the concepts "pass by reference" and "object reference" have in common is that they both use the word "reference." In the former, it's a reference to a variable [and a concept JavaScript doesn't have]. In the latter, it's a reference to an object.)

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us Javascript

©2020 All rights reserved.