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);
   }
}

1 Answer 1

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);
3
  • 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: stackoverflow.com/a/122704/761793 Commented Mar 6, 2013 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! Commented Mar 6, 2013 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
    Commented Mar 6, 2013 at 16:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.