0

When a user clicks a button, I'm grabbing the availableTags array, storing it in a new var tagsToWorkWith. I then iterate over tagsToWorkWith and run moveTag() on each row in order to move every tag that was in availableTags.

Inside of moveTag(), I'm removing that row from availableTags using splice(). However, for some reason, this is removing the row from tagsToWorkWith, which causes my for() function to only run moveTag() on every other row.

Why is splice() removing the row from tagsToWorkWith? I'm explicitly setting tagsToWorkWith equal to the original availableTags to avoid this problem, but that doesn't seem to be working.

The below code runs with the error at http://jsfiddle.net/EdnxH/

var availableTags = [{"label":"Label A","value":"1"},{"label":"Label B","value":"2"}, {"label":"Label C","value":"3"}];

$(document).on('click', '#clickButton', function () {
    var tagsToWorkWith = availableTags;                         
    for(var countera=0; countera< tagsToWorkWith.length; countera++) {
        alert(tagsToWorkWith[countera].label);
        moveTag(tagsToWorkWith[countera].label, tagsToWorkWith[countera].value);
        //This should match the first alert label, since we haven't increased the counter yet. But, for some reason, moveTag()'s splice() removes the row from tagsToWorkWith.
        alert(tagsToWorkWith[countera].label);
    }   
});

function moveTag(itemToMove, itemToMoveValue) {
   var selectedTagArrayIndex = -1;    
   for(var counter=0; counter< availableTags.length; counter++) {
       if (availableTags[counter].value == itemToMoveValue) {
           selectedTagArrayIndex = counter;
       }
   } 
   if (selectedTagArrayIndex > -1)  {
       availableTags.splice(selectedTagArrayIndex, 1);
   }
}
Luke Shaheen
  • 4,262
  • 12
  • 52
  • 82

1 Answers1

4

Arrays are objects, and objects are not "deep copied" when you assign references between variables. Thus, both your variables are referencing the exact same object.

Thus:

var a = ["hello", "world"];
var b = a;
a[2] = "again";
alert(b[2]); // "again" because "a" and "b" are the same object

If you want to make a copy of an array, you can use:

var b = a.slice(0);
Pointy
  • 405,095
  • 59
  • 585
  • 614
  • Works perfect, thank you for that note about the deep copying. Since I'm already loading the jQuery library, do you know if there is a major speed difference between `a.slice(0)` and `jQuery.extend(true, {}, a);` as referenced here: http://stackoverflow.com/a/122704/761793 – Luke Shaheen Mar 06 '13 at 15:55
  • After reading through more of the answers at the referenced question, I see `slice(0)` does more of a soft clone, different then the function I referenced. I'll keep doing more reading and move on, thanks! – Luke Shaheen Mar 06 '13 at 15:59
  • @John yes, it's a "shallow" copy. If the array has objects in it, then those objects are not deep-copied. – Pointy Mar 06 '13 at 16:02