Reputation: 13207
I am extending shat with shot. After extending, why does modifying shot alter shat?
var shat = [{bang:true}, {bumm: false}, {bong: false}]
var shot = [{bang:false}, {bumm: false}, {bong: false}]
$.extend(shat, shot)
shot[0].bang = true
console.log("shat", shat)
// prints
Object
bang: true // why is this true?
Object
bumm: false
Object
bong: false
I am assuming a reference is created or the extending is for some reason happening after the shot[0].bang = true. The problem is, I want to modify shot after the extending, but of course dont want to have it any effect on shat. Any ideas why this is happening and what I could do to avoid that?
see jSfiddle testcase: http://jsfiddle.net/yEnph/3/
Upvotes: 5
Views: 3012
Reputation:
By default, $.extend
merely shallow-copies properties*. It's not very exciting.
In this case, the extended properties are "0", "1", "2", etc, and thus shat[0] === shot[0]
is true after extending which is only the case if both evaluate to the same object. Since they are the same object then ... well, mutating it one place mutates it everywhere.
To keep them separate consider a "deep copy" (see the different ways to invoked jQuery.extend). Another approach, that I mention because it can also be used in other contexts, is to serialize the object and then de-serialize it -- e.g. with JSON.
var shat = [{bang:true}, {bumm: false}, {bong: false}]
var shot = [{bang:false}, {bumm: false}, {bong: false}]
$.extend(true, shat, shot) // use "deep copy"
shat[0] === shot[0] // false; different objects now so...
shot[0].bang = "boom" // ...this will not affect the object named by shat[0]
shot[0].bang // "boom"
shat[0].bang // false
Happy coding.
*That is, for every property, p
, in the source object(s), it merely does target[p] = source[p]
. Remember that, in JavaScript, Arrays are just a special subtype of object with a magical length
: the value at index n is named by the property "n".
Upvotes: 7
Reputation: 78650
Interesting that that works at all, wasn't aware that extend
worked on arrays.
The reason for this though is that the two arrays both contain a reference to the same object. It's the same reason that this will alert "new":
var a = { test: "one"};
var b = a;
a.test="new";
alert(b.test);
Both variables have a reference to the same object so editing the object updates the object, which they both reference.
Upvotes: 1
Reputation: 140230
Extend just overwrites the properties if the keys are taken:
var a = {
hello: "kitty"
},
b = {
hello: "world"
}
$.extend( a, b );
console.log( a );
//Object
//hello: "world"
Because arrays are just objects with numeric property names, you will replace them with same principle except "hello"
is "0"
, and so on.
Because you have objects instead of primitives, shat
gets shot
's objects, they are rewritten so the original shat
objects are lost. So modifying shot
's objects will modify shat
's objects because they are the same objects.
Upvotes: 0
Reputation: 5679
From the jQuery document http://api.jquery.com/jQuery.extend/, it looks like $.extend only does Object augments, but not Array. In the example, your shat
variable has never been changed.
Upvotes: 2