2

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.

0

2 Answers 2

1

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
Sign up to request clarification or add additional context in comments.

3 Comments

thanks for clarification. well i am a bit heartbroken. i was expecting a bit more. os as far i understood from your post that closures makes sense only when you are using some value type? the well known ubiquitous loop example is just good to have incrementing value type. if it never works for reference type then i might just assign it some temp variable.
@mobygeek closures are about the values of variables. A reference to an object (or an array) is a value itself. That's what gets saved in the closure. However, the contents of any object or array can be changed, because JavaScript objects are mutable. That's true whether there's a closure involved or not. If you want to save the contents of an object, you have to do that explicitly.
@mobygeek "closures makes sense only when you are using some v̶a̶l̶u̶e̶ primitive type", not really, "a closure lets you associate some data with a function that operates on that data" (MDN), this is its main purpose, regardless the primitive/composite nature of this data. In your situation, a closure remains useful with a deep copy of your object. Indeed, it's able to store the data for a later use, without the need of a more complex object oriented style, and without polluting the upper scopes.
0

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.

4 Comments

well newacct, thank you for contribution. and my bad that i used the "word pass by reference", you are right i had to make it clear that meant to say passing reference by value.
i have clear understanding of what is reference and what is value. and i was not expecting to see in javascript something like "ref" keyword in c#. any way whole point was that i initally thought that even i pass a reference by value(copy of refence not object) the engine will be creating sort of deep copy of it and will save it within closure. that was my impression. that's all, seems not, there is much ado about, hyping closure. we usually do it everyday in other languages.
so correct if i m wrong closure is useful if you planning to destroy/forget the original value. so that since there is a closure(your inner function referencing) it will be hung around for you. but if you are not planning to trash the original then they are identical. no point of relying on closure.
@mobygeek: in this case, there's no point on using the closure to assign arr (the original value of c.internalarray) to c.internalarray, since they are the same, since you did not assign to c.internalarray in between

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.