Björn
Björn

Reputation: 13207

Is jQuery´s extend creating a reference between the objects?

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

Answers (4)

user166390
user166390

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

James Montagne
James Montagne

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":

http://jsfiddle.net/yEnph/4/

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

Esailija
Esailija

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

Grace Huang
Grace Huang

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

Related Questions