user1649326
user1649326

Reputation: 257

Pushing an object onto an array, manipulation changes every element

In JavaScript I have an array. I'm using push() to add array elements, but when I manipulate said elements, each array element is changed, when only one should be. My code is:

// Arrays to hold the elements that have been created (added to the document).
create.element_array                       = []
create.element_array["name"]               = []
create.element_array["name"]["properties"] = []

var element_properties = 
{
    // Default all to 0.
    borderTopStyle: 0, borderRightStyle: 0, borderBottomStyle: 0, borderLeftStyle: 0,
    borderTopWidth: 0, borderRightWidth: 0, borderBottomWidth: 0, borderLeftWidth: 0, 
    borderTopColor: 0, borderRightColor: 0, borderBottomColor: 0, borderLeftColor: 0,
}

// Testing purposes. These will be added dynamically in production version.
create.element_array["name"].push("default_header");
create.element_array["name"]["properties"].push(element_properties);

create.element_array["name"].push("default_body");
create.element_array["name"]["properties"].push(element_properties);

create.element_array["name"].push("default_footer");
create.element_array["name"]["properties"].push(element_properties);

// Evidence that each array element is changed with index manipulation.
create.element_array["name"]["properties"][0].borderTopStyle = "dashed";

console.log(create.element_array["name"]["properties"][0]);
console.log(create.element_array["name"]["properties"][1]);
console.log(create.element_array["name"]["properties"][2]);

The result I expect from this is that ONLY index 0 should be changed, but this is not the case. The above console.log lines will output the following:

Object
borderBottomColor: 0
borderBottomStyle: 0
borderBottomWidth: 0
borderLeftColor: 0
borderLeftStyle: 0
borderLeftWidth: 0
borderRightColor: 0
borderRightStyle: 0
borderRightWidth: 0
borderTopColor: 0
borderTopStyle: "dashed"
borderTopWidth: 0
__proto__: Object
 library.js:8
Object
borderBottomColor: 0
borderBottomStyle: 0
borderBottomWidth: 0
borderLeftColor: 0
borderLeftStyle: 0
borderLeftWidth: 0
borderRightColor: 0
borderRightStyle: 0
borderRightWidth: 0
borderTopColor: 0
borderTopStyle: "dashed"
borderTopWidth: 0
__proto__: Object
 library.js:8
Object
borderBottomColor: 0
borderBottomStyle: 0
borderBottomWidth: 0
borderLeftColor: 0
borderLeftStyle: 0
borderLeftWidth: 0
borderRightColor: 0
borderRightStyle: 0
borderRightWidth: 0
borderTopColor: 0
borderTopStyle: "dashed"
borderTopWidth: 0
__proto__: Object
 library.js:8

Why is borderTopStyle being changed for every element, when I explicitly define index 0 to be the only index that gets changed?

Upvotes: 0

Views: 407

Answers (3)

Bruno
Bruno

Reputation: 5822

You need to create new instances of the element_properties object. Like so:

var properties_el = Object.create( element_properties );

create.element_array["name"].push("default_header");
create.element_array["name"]["properties"].push( properties_el);

At the moment you are inserting the same object 3 times. Another option would be to use an object to store your properties like so:

create.element_object = {};
create.element_object["name"] = properties_el;

This allows you to access properties in the following way

create.element_object["name"]["borderTopStyle"]

or

create.element_object.name.borderTopStyle

Just an idea.

Upvotes: 2

aepheus
aepheus

Reputation: 8187

Objects are passed by reference in javascript. Quite literally:

element_properties == create.element_array["name"]["properties"][0] == create.element_array["name"]["properties"][1]

You can remedy this using the new operator, or using different object literals.

Upvotes: 2

JasonWyatt
JasonWyatt

Reputation: 5303

You are adding the same reference to the element_properties object to each spot in the array. This means that when you try to change it, you're changing the value of the object pointed-to by that reference.

You might want to instead use a constructor the properties object:

function ElementProperties(){
}
ElementProperties.prototype = {
    // Default all to 0.
    borderTopStyle: 0, borderRightStyle: 0, borderBottomStyle: 0, borderLeftStyle: 0,
    borderTopWidth: 0, borderRightWidth: 0, borderBottomWidth: 0, borderLeftWidth: 0, 
    borderTopColor: 0, borderRightColor: 0, borderBottomColor: 0, borderLeftColor: 0,
};

Then, something like this:

create.element_array["name"].push("default_header");
create.element_array["name"]["properties"].push(new ElementProperties());

Upvotes: 1

Related Questions