Javascript closure, external object support

I used Javascript closure to protect variables by making them local to return functions, for example:

closure = function() { var secretVar = 'Secret'; return { "msg" : function() { console.log(secretVar); } }; }(); console.log(closure.secretVar); // Undefined closure.msg(); // Secret 

I feel like I have a pretty good idea of ​​this, giving me the ability to control access to internal variables, if at all possible.

Now i am facing 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 shut.del () to return Secret One, but I want secretVar to remain untouched, but that is not the case. The del () function modifies the link, not the copy, and I'm not sure how to make it copy secretVar and change this.

I guess it will be in shape

 (function(y) { //..Body that changes y })(secretVar) 

but I could not get this to work. Any ideas?

+4
source share
4 answers

Your problem actually has nothing to do with closure. When you do:

 modMe = secretVar; 

You simply create a new variable pointing to the same array. What you do with one will be reflected in both variables as they point to the same thing.

If you want to perform any modification in the array (while saving the original), you need to copy it first:

 var copied = []; for(var i = 0; i < secretVar.length; i++){ copied.push(secretVar[i]); } 

Editing: aside, when you say that you use locks to “protect variables”, you do not protect them from being changed by the return functions that performed the closure. You simply made it so that the variable is not accessible from outside these functions. But inside the scope, for example, when you make your fragment, the variable exists and is accessible to this function and is not "protected" just because it is a closure.

Edit 2: If you are going to frequently copy the array, you can eliminate some annoying iteration by creating a private copy function 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(); } }; }(); 
+7
source

Very close - form:

 (function(y) { return function() { // that changes y }; })(secretVar) 

NOTE. . It will still pass the link, and any destructive or changing operations will still affect secretVar . You need to make a deep copy of secretVar if you want to avoid changing it.

SM.: Http://jsfiddle.net/B3ryr/2/

+1
source

Robert made a good comment, but also noted that closure.del not a function, but undefined. Look at your code again. 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); 

Usually this form:

 var a = function(b){ console.log(b) }('input'); console.log( typeof a ); // undefined a(); // error: a is not a function 
0
source

Your expression function(modMe) { ... }(secretVar) actually returns a value, not a function, since you are executing a function. Combined with Matt's answer, you need to:

  • Remove the component (secretVar) from the expression, as well as the modMe parameter - the function already has access to secretVar anyway.
  • Actually copy the array before working on it. See Matt's answer.
0
source

All Articles