Tom Maitland
Tom Maitland

Reputation: 578

Scoped variable is creating a reference instead of new instance

Experiencing a weird Javascript bug it'd be great to get some insight to. I've managed to debug it to know what the issue is, I just haven't been able to figure out the why yet and a non-hackey way to resolve it.

I'm trying to create a new instance of an array as a variable inside a function, so I can manipulate it without affecting the main array. Instead I'm getting some kind of reference, so doing operations on my new variable ids also affects the array that ids equals.

I've simplified my code to demonstrate the issue more clearly:

var defence = {

    selectedIDs: new Array(),

    toggleTerm: function(term, id) {

        // add to the main array
        this.selectedIDs.push(5);

        // adds to this.selectedIDs
        this.showTweet();

    },

    showTweet: function() {

        // copy the array as a new variable in the scope of the function
        var ids = this.selectedIDs;

        if (ids.length == 1) {
            ids.push(10); // this pushes to 'ids' AND 'this.selectedIDs'
        }
        console.log(this.selectedIDs); // outputs [5, 10]

    }

}

Also in JSFiddle

It's always been my understand that var ids = this.selectedIDs would effectively copy the contents of this.selectedIDs into that new instance - however this doesn't seem to be the case.

Any ideas on why this is happening, and the best way to get around it (beyond manually recreating it through something like a for loop)?

Upvotes: 1

Views: 49

Answers (2)

Michael Lorton
Michael Lorton

Reputation: 44406

It's always been my understand that var ids = this.selectedIDs would effectively copy the contents

OK, but your understanding is wrong. It's an assignment.

Consider this instead:

var ids = this.selectedIDs.slice()

Upvotes: 2

Ry-
Ry-

Reputation: 225044

It's always been my understand that var ids = this.selectedIDs would effectively copy the contents of this.selectedIDs into that new instance - however this doesn't seem to be the case.

I don’t know how to describe this except “no, that doesn’t happen at all”. JavaScript isn’t C++; when you assign something to a variable, it is never copied. You always get a reference, except in the case of primitives, which are immutable, making the point moot. (Heh.)

You could use concat, but if this isn’t the actual situation, there might be something more appropriate.

showTweet: function() {
    var ids = this.selectedIDs;

    if (ids.length === 1) {
        ids = ids.concat(10); // Array.prototype.concat returns a new array
    }

    console.log(this.selectedIDs); // outputs [5]
}

Upvotes: 0

Related Questions