1

I have a JSON array named arr and a new array named new_arr that is created from arr.

var arr = {"data":
 [
  {"name":"Alan","height":"171","weight":"66"},
  {"name":"Ben","height":"182","weight":"90"},
  {"name":"Chris","height":"163","weight":"71"}
 ]
};

var new_arr = arr;

new_arr.data = jQuery.grep(new_arr.data, function(n, i){
  return n.weight > 70;
});

Both arrays arr and new_arr becomes:

{"data":
 [
  {"name":"Ben","height":"182","weight":"90"},
  {"name":"Chris","height":"163","weight":"71"}
 ]
};

My question is: "Why does modifying the new array changes the old one?"

Question Overflow
  • 10,925
  • 18
  • 72
  • 110

4 Answers4

5

There is no new array. It's just a new reference to the old array.
Try it in another example :

var a = {};
var b = a;
// check to see if they are equal
alert(a === b);
// modify one of them 
b.foo = 'bar';
 // check to see if they are equal
alert(a === b);
// modify one of them 
a.bar = 'foo';
 // check to see if they are equal
alert(a === b);

a and b refer to the same object, thus, when you modify a you also modify b and so on.

If you use jquery you should use the extend method :

var new_arr = $.extend(true,arr);
gion_13
  • 41,171
  • 10
  • 96
  • 108
2

You're referencing the same Array when you do:

var new_arr = arr;

If you want a copy, you need to make a copy:

var new_arr = arr.data.slice( 0 ); // 0 is the optional starting index of the copy

This just makes a shallow copy of the Array, so the nested objects will be referenced by both.

If you need a deep clone of all nested objects, you'd need to traverse into each individual object, and make a copy.

user113716
  • 318,772
  • 63
  • 451
  • 440
  • I'm curious whether passing `0` is recommended? `arr.slice()` should work as well or are there any issues in certain browsers I'm not aware of? – Felix Kling Sep 21 '11 at 14:15
  • @FelixKling: No, it's not needed since `0` is default, and I don't know of any browser issues. I just thought I had better be a little more explicit in this case. Added a code comment to clarify. :) – user113716 Sep 21 '11 at 14:16
  • Ok, I just saw many people doing this recently and was wondering... :) Thanks! – Felix Kling Sep 21 '11 at 14:18
  • just because he named it `arr`, it doesn't make it an array. It's actually an object, and calling `slice` on it would trigger an error. – gion_13 Sep 21 '11 at 14:23
  • I need a deep copy. The extend method works perfectly. Thanks for your suggestion too :) – Question Overflow Sep 21 '11 at 14:29
  • 1
    @gion: I assume patrick was confused by the description, where it says *JSON array*. – Felix Kling Sep 21 '11 at 14:35
  • Yes, I didn't look closely enough. Updated my answer. – user113716 Sep 21 '11 at 14:36
  • @Felix Kling : I wasn't being mean, but I assumed that as confused as he may have been, he would've just copy/paste the code and return to SO with an error msg – gion_13 Sep 21 '11 at 14:41
  • @gion: I know, I know :) Just wanted to explain where the error might come from. You are absolutely right in pointing it (heck, I overlooked that too!). – Felix Kling Sep 21 '11 at 14:46
1

You should clone your array instead. I copied this from John Resig over here. See his post for more explanation.

// Shallow copy
var newObject = jQuery.extend({}, oldObject);

// Deep copy
var newObject = jQuery.extend(true, {}, oldObject);

This should work for your arr and new_arr.

Community
  • 1
  • 1
Cᴏʀʏ
  • 105,112
  • 20
  • 162
  • 194
-1

may be because arr is an object and var new_arr = arr just assigns reference to it to new_arr ? try this new_arr = arr.clone()

skazska
  • 421
  • 2
  • 8