Eirik M
Eirik M

Reputation: 816

When updating an array in a JavaScript object the prototype is updated. Why?

Kind of strange thing is happening with my code. What I observe is something like this:

var prototype = {
    property : "",
    array : []
}

var objectArray = [];

function myFunction {
    objectArray[0] = Object.create(prototype);
    objectArray[1] = Object.create(prototype);

    objectArray[0].property = "Hello 1";
    objectArray[0].array.push("Hello 1");
    objectArray[1].property = "Hello 2";
    objectArray[1].array.push("Hello 2");

    // At this point when running the program I get:
    // objectArray[0].property == "Hello 1"
    // objectArray[1].property == "Hello 2";
    // objectArray[1].array == objectArray[1].array == prototype.array
    // == ["Hello 1", "Hello 2"]
}

What I want, and expected, was two separate arrays for the two objects. What am I missing here?

Upvotes: 0

Views: 127

Answers (4)

Matt Brock
Matt Brock

Reputation: 5391

Don't forget that Object.create() isn't yet standardized, and won't work in IE8 or FF3.6. A simple work-around to clone an object is to use the JSON object:

function clone(obj) {
  return JSON.parse(JSON.stringify(obj));
}

Upvotes: 0

bfavaretto
bfavaretto

Reputation: 71908

I wonder if you aren't asking yourself "why does it work for property, but not for array?". The fact is, it doesn't work for property either, JavaScript is fooling you.

When objects share the same prototype, one must consider that:

  • All properties of the prototype are shared by the objects that inherit from that prototype.
  • You cannot assign to properties of the prototype, only read them (unless it's an accessor property, but let's keep that aside).

So what's actually happening here:

objectArray[0].property = "Hello 1";
objectArray[1].property = "Hello 2";

is that a new own property called "property" is being created on each object, while prototype.property remains untouched. The array property is behaving differently because you're not assigning to it, you're accessing prototype.array and calling the push method on it.

Upvotes: 0

David Hellsing
David Hellsing

Reputation: 108480

In JavaScript, objects are copied by reference, so both objectArray objects are simply references to the same object ( prototype ). You need to clone the object or create instances using the new keyword and a constructor to create separate objects.

Example on how to do it using the new keyword:

var prototype = function() {
    this.property = "";
    this.array = [];
};

objectArray[0] = new prototype();
objectArray[1] = new prototype();

You can also do:

var prototypeFactory = function() {
    return {
        property: "",
        array: []
    };
};

objectArray[0] = prototypeFactory();
objectArray[1] = prototypeFactory();

Upvotes: 1

alex
alex

Reputation: 490143

The prototype object exists the same as the [[Prototype]] for each object. They don't get a fresh copy when you use Object.create().

You'd need to use assignment, which never walks the prototype chain.

Upvotes: 0

Related Questions