mobygeek
mobygeek

Reputation: 193

javascript closures and object reference

i am a bit obscure situation. mainly because i thought i already grasp closures. so basically what i want is to reset to default values a collection. so let say i have collection which has constructor with array of objects parameter.

 var c = new collection([{x},{y},{z}]);

then collection periodically get updated.since i am not keeping somewhere initial values of array, after sometime i would like to reset to initial values.

now i am not asking how to implement this, there could be multiple ways my question about closures itself. please read further

so the way i might thought to trap this initial value using closures so it might look like this.

c.on('reset',(function(arr){

    return function(){

          c.internalarray = arr;

    }

 })(c.internalarray))

so it is not working seems because the reference is passed as argument the collection updates the suppossedly trapped arr also get updated its end up always true for

arr === c.internalarray;

i might thought to pass the clone of array but what is the point is not that somewhere just creating a copy of data with assigning keeping global variable.

so my question what i am doing wrong. i thought that somehow implicitly javascript engine creates a copy of trapped variable/object. that i dont have to keep track of them.

Upvotes: 2

Views: 1704

Answers (2)

user1636522
user1636522

Reputation:

In javascript, composite data types are passed by reference, so, c.internalarray and arr both refer to the same value. Actually, you were on the right way, but you have to make a copy of the array before passing it to your immediately invoked function. For example :

c.on('reset', function (arr) {
    return function () {
        c.internalarray = arr;
    }
}(c.internalarray.slice()));

That said, this technique will not create a deep copy, meaning that composite types contained in the array are still mutable from the outside of the immediately invoked function. In the code below, I've tried to simplify this situation in order to make things easier to understand, hopefully :

The variable a refers to an array which contains two elements :

var a = [
    1, // primitive value
    {} // composite value
];

Let's make a shallow copy of a and assign it to b :

var b = a.slice();
// a -> [1, {}]
// b -> [1, {}]
// b === a -> false

Removing the first element from a has no effect on b :

a.shift();
// a -> [{}]
// b -> [1, {}]

But modifying the object contained in a affects b as well :

a[0].k = 'value';
// a -> [{ k: "value" }]
// b -> [1, { k: "value" }]
// a[0] === b[1] -> true

Upvotes: 1

newacct
newacct

Reputation: 122439

This has nothing to do with closures. Your issue can be seen simpler with this:

var internalarray = [{x},{y},{z}];
var arr = internalarray;

// "update" internalarray here

arr === internalarray // still true
internalarray = arr; // This statement has no effect

Just like in Java, every value in JavaScript is either a primitive or a reference (a pointer to an object). The value of arr is a pointer to an object, the value of c is a pointer to an object, the value of c.internalarray is a pointer to an object, etc. Specifically in this case, c.internalarray is a pointer to an array object. Assigning one pointer to another simply makes the second one point to the object pointed to by the first one. When you do arr = internalarray; (or in your code, when you pass c.internalarray in to a function as the parameter arr), you have two pointers that point to the same object.

When you say "collection periodically get updated", you are never assigning (as in =) to c.internalarray itself. That's why arr === c.internalarray remains true -- since you assigned one to the other initially, the only way they could be not equal is if you assigned to one of them later. Instead, I am guessing you are changing the elements of the array pointed by these two variables, using subscript operator like c.internalarray[foo] = bar; or calling a method like c.internalarray.push(bar);. Since you are changing the object pointed to, multiple pointers that point to it will be able to see the changes.

Upvotes: 0

Related Questions