3

I'm trying to save a copy of the array before I sort it:

words_Array = ["Why", "doesnt", "this", "work?"];

var sortedWords_Array = words_Array;

sortedWords_Array.sort(function(a, b){
    return b.length - a.length;
});

alert("sortedWords_Array is :"+sortedWords_Array);
alert("words_Array is :"+words_Array);

After I sort sortedWords_Array, they're both sorted for some reason. http://jsfiddle.net/zv39J/ Why is that?

Squirrl
  • 4,909
  • 9
  • 47
  • 85
  • 2
    *"Why is that?"* Because `words_Array` and `sortedWords_Array` refer to the same array. Assigning an array to a variable does not create a copy of it. – Felix Kling Nov 17 '13 at 04:32
  • Ok works. Sry for the repeat question, I didn't find it. I'll vote correct as soon as they let me. Thanks everyone. – Squirrl Nov 17 '13 at 04:36

4 Answers4

16

Because in javascript, arrays are passed by reference which means that when you make one array equal to another it will change both whenever you make an edit to one. To fix this in your example change the following line:

var sortedWords_Array = words_Array;

to:

 //make a copy of array by using slice
 var sortedWords_Array = words_Array.slice(0);

See here for other uses and a more in-depth explanation:

slice does not alter the original array, but returns a new "one level deep" copy that contains copies of the elements sliced from the original array.

Array.prototype.slice()

Villarrealized
  • 867
  • 1
  • 6
  • 13
2

Use the slice function to make a fast copy.

http://jsfiddle.net/zv39J/2/

On another note—alerts are terrible. No one wants to click a jsfiddle only to be greeted by a series of alert windows. I've updated the fiddle to include jQuery, which allows us to use a nice succinct syntax to make updates to the HTML.

DaoWen
  • 32,589
  • 6
  • 74
  • 101
  • @Squirrl - You don't need to accept my answer, but please take note of my comment about the alerts in your jsfiddle. I'm sure everyone would appreciate it if in the future you would use a format more like that in my updated fiddle rather than using alerts. – DaoWen Nov 17 '13 at 04:49
  • 1
    Okay. I apologize. Will do from now on. THanks again. – Squirrl Nov 17 '13 at 04:50
  • @Squirrl - OK, great! Thanks for posting the jsfiddle in the first place. That really makes it easier to get right to playing with your code. It's just easier when it's not using alerts to show the results. ^_^ – DaoWen Nov 17 '13 at 04:52
2

Do a slice() on the array to duplicate, and then sort.

var sortedWords_Array = words_Array.slice();
UltraInstinct
  • 43,308
  • 12
  • 81
  • 104
2

This wont work because when you try to assign var sortedWords_Array = words_Array;

The reference of words_array is passed to sortedWords_Array. So any change made to sortedWords_Array will be reflected on words_array.

Since Array.slice() does not do deep copying, it is not suitable for multidimensional arrays:

var a =[[1], [2], [3]];
var b = a.slice();

b.shift().shift();
// a is now [[], [2], [3]]

Note that although I've used shift().shift() above, the point is just that b[0][0] contains a pointer to a[0][0] rather than a value.

Likewise delete(b[0][0]) also causes a[0][0] to be deleted and b[0][0]=99 also changes the value of a[0][0] to 99.

jQuery's extend method does perform a deep copy when a true value is passed as the initial argument:

var a =[[1], [2], [3]];
var b = $.extend(true, [], a);

b.shift().shift();
// a is still [[1], [2], [3]]
Augustus Francis
  • 2,694
  • 4
  • 22
  • 32
  • Thanks. THis was a really indepth answer as well. If I need to copy multidemensional arrays in the future i'll be sure to look at it. Thanks a lot. – Squirrl Nov 17 '13 at 04:54