Reputation: 3674
I've been using Javascript closures to protect variables by making them local to the returned functions, such as:
closure = function() {
var secretVar = 'Secret';
return {
"msg" : function() {
console.log(secretVar);
}
};
}();
console.log(closure.secretVar); // Undefined
closure.msg(); // Secret
I feel that I have a pretty good grasp of that, giving me the ability to control how inner variables are accessed if at all.
I'm now running into this problem
closure = function() {
var secretVar = ['Secret One','Secret Two'];
return {
"del" : function(modMe) {
modMe = secretVar;
modMe.slice(1,1);
console.log(modMe);
}(secretVar),
"secretVar" : function() {
console.log(secretVar);
}
};
}();
closure.del(); // Secret One
closure.secretVar(); // Secret One
I want closure.del() to return Secret One, but I want the secretVar to remained untouched, however, it's not. The del() function is modifying the reference rather than a copy, and I'm unsure of how to get it to copy secretVar and modify that.
I'm guessing it's going to be in the form of
(function(y) {
//..Body that changes y
})(secretVar)
but I haven't been able to get that to work. Any ideas?
Upvotes: 4
Views: 639
Reputation: 41832
Your problem actually has nothing to do with closures. When you do:
modMe = secretVar;
You are just creating a new variable pointing to the same array. What you do to one will be reflected in both variables, since they are pointing to the same thing.
If you want to perform some sort of modification on the array (while maintaining the original), you need to copy it first:
var copied = [];
for(var i = 0; i < secretVar.length; i++){
copied.push(secretVar[i]);
}
Edit: As an aside, when you say you are using closures to "protect variables" you're not protecting them from being modified by the returned functions that performed the closure. You just made it so that the variable is inaccessible from outside the scope of those functions. But, inside the scope, such as when you do your slice, the variable is there and accessible to that function and is not "protected" just because it is a closure.
Edit 2: If you are going to be copying the array frequently, you can eliminate some of the irritation of the iteration by creating a closured function to do the copying for you:
closure = function() {
var secretVar = 'Secret';
var clone = function(){
var clonedArr = [];
var length = secretVar.length;
for(var i = 0; i < length; i++){
clonedArr.push(secretVar[i]);
}
return clonedArr;
}
return {
"msg" : function() {
var duplicate = clone();
}
};
}();
Upvotes: 7
Reputation: 159995
Very close -- the form is:
(function(y) {
return function() {
// that changes y
};
})(secretVar)
NOTE: This will still pass a reference, and any destructive or altering operations will still affect secretVar
. You'll need to make a deep copy of secretVar
if you want to avoid altering it.
SEE: http://jsfiddle.net/B3ryr/2/
Upvotes: 1
Reputation: 169143
Your function(modMe) { ... }(secretVar)
expression is actually returning a value and not a function, since you are executing the function. Coupled with Matt's answer, you need to:
(secretVar)
component from the expression as well as the modMe
parameter -- the function already has access to secretVar
anyway.Upvotes: 0
Reputation: 22438
Robert made a good comment, but also note that closure.del
is not a function, but undefined. Take another look at your code. The function is automatically executed and returns nothing, so del will be nothing.
var del = function(modMe) {
modMe = secretVar;
modMe.slice(1,1);
console.log(modMe);
}(secretVar);
It's generally this form:
var a = function(b){
console.log(b)
}('input');
console.log( typeof a ); // undefined
a(); // error: a is not a function
Upvotes: 0