Bind a changing variable in function, I want a name - javascript

I have somethings like:
var i = 0;
var func = function(){
console.log(i);
};
func(); //0
i++;
func(); //1
I want to have the second console also output '0',
so I change the program like:
var i = 0;
var func = (function(_i){
return function(){
console.log(_i);
};
})(i);
func(); //0
i++;
func(); //0
I know how it works, but is there any name or terms to describe such mechanism?

I've been calling this mechanism "breaking the closure" though I've had arguments in the past with people who insist on calling this technique "closure".
The reason I call it "breaking" closures is because that's what you're doing.
The classic place where you see this is in solutions for closures in loops:
var hellos = [];
for (var i=0; i < 10; i++) {
hellos.push(
(function(j){
return 'hello ' + j
})(i)
);
}
The problem is caused by a closure being created between the outer variable and references to that variable in the inner function (technically the variable is called a "free" variable rather than a closure, "closure" technically refers to the mechanism that captures the variable but in the js community we've ended up calling both things closures). So closure is the cause of the problem. Since the problem is caused by a closure being created I've started referring to the solution as "breaking the closure".
Note that even though some people call this a closure and you may google for "js closure" to read more about this technique it is ironically not a closure. What it is is simply how functions pass arguments (there's a whole side-argument about how javascript actually pass arguments to functions which you can read here: Why are objects' values captured inside function calls?). Javascript is a fairly strict pass-by-value language in the same way C is a strict pass-by-value language (C can ONLY pass by value).
When you pass a reference in js (objects, arrays) the function will not get the original reference but rather a copy of the reference. Since it is a reference it obviously points to the same object as the original reference so it is easy to mistakenly believe that javascript passes by reference. But if you try to assign a new object to the passed-in reference you will notice that the original reference does not change. For example:
function foo (x) {
x = [2,3];
}
var y = [1,2];
foo(y);
console.log(y) // prints [1,2] so foo() did not change y
It is this mechanism that is responsible for breaking the association between the outer variable (in your example that would be i) and the inner variable (_i in your example). The name of this mechanism is simply function calling (well, technically it is a subset of function calling - it is how arguments are passed to function calls).
So to recap:
I personally call it "breaking the closure"
Some people call it "closure" even though it is not a closure (the closure is what they want to avoid instead).
Side note: I realize that the original example is about a global variable but in javascript global variables are just a special case of closures - closures are ALWAYS created when you define a function, it's just that when there's no outer function the outer scope is simply the global scope.

It's called a closure. You can read more about them here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures

When passing in a primitive type variable like a string or a number, the value is passed in by value. This means that any changes to that variable while in the function are completely separate from anything that happens outside the function.
if the variable in the scope is not declared, it will search the outer scope, until find it, or to the window scope. if not find, it will the variable global.

Related

Javascript Closures and variable scope when function call ends

I have read this excellent piece:
How do JavaScript closures work?
But I still have questions...
StackOverflow tags defines "Closures" as "A Closure is a first class function that refers to (closes over) variables from the scope in which it was defined. If the closure still exists after its defining scope ends, the variables it closes over will continue to exist as well".
When my functions end with a return, do all variables defined within them get deleted and memory allocation made free? It appears to me that conditions exist when one could answer yes or no.
Yes, I know memory is plentiful and free but that is not my question.
Think of an intranet based application which ajax's data back and forward during a working day. As data is received by the client, massaged, and no longer required, it can be dispensed with. Poor programming technique could result in a build up of data no longer user or required (or worse, data being used that is out of sync).
Reading the piece on closures above tells me that some variables within a function can still be referenced from outside the function scope. I am guessing that I will need to re-read the closure document several times as perhaps I've not fully understood it.
Can someone share an example on where a variable continue to exist?
And... Do I gain any benefit if, at the begining of each function I declare my variables, and prior to using a "return true;" if I reassign the variables a value of null?
All help appreciated...
num will exist within a function outside of IIFE c which returns a
var c = (function() {
var num = 10;
var a = function a(n) {
console.log(n)
return n * Math.random()
};
return a.bind(null, num)
}());
var res = [c(), c(), c()];
console.log(res)
When you return true from a function you don't have a closure. You have a closure when you return a function from a function, like this:
function makeAdder( firstNumToAdd ){
return function( secondNumToAdd ){
return mainNumToAdd + secondNumToAdd;
}
}
var add3 = makeAdder(3);
var seven = add3(4);
In the above example, the variable firstNumToAdd, although is scoped to the function makeAdder is always accessible to the inner function, even though the function exited after executing the line var add3 = makeAdder(3);
Please correct me if I am wrong, but I don't think that
some variables within a function can still be referenced from outside the function scope
is true.
Closures remember the context of a function call and bind the relevant variables (i.e. this, etc) to the closure's scope. If that is correct, then calling the closure again would cause the old variables' values to get garbage collected and you wouldn't have to worry about memory waste or out of sync data.
obj = {
func: function(){
var test = 'preserved value';
this.func2 = function(){
console.log(test);
};
}
};
obj.func();
obj.func2(); //'preserved value'
obj.func = undefined;
obj.func2(); //'preserved value'
As you can see, even after completely blowing away the original scope (func) the enclosing scope retains the test var.

Is it possible to Detect Closure Programmatically?

I have a function which allows user to pass a function.
function withPredicate(func){
//...
}
Inside my function, I need to detect whether the func that user pass in has closure or not.
It is not enough to get the function name and search it in window scope. User might pass in an anonymous function without closure like:
var func = function(x){return x;};
withPredicate(func);
EDIT:
I think I need to implement a function which takes a function as a argument and return bool.
function hasClosure(func){
//...
}
so several test cases are:
hasClosure(function(x){return x;}); //return false
var something = 30;
var func1 = function(x){return x.age < something;}
hasClosure(func1); //return false
var Closure = function(){
var something = 18;
var itself = function(x){
return x.age < something;
};
return itself;
};
var func2 = new Closure();
hasClosure(func2); //return true
The last one return true because func2 is not top-level function. When I see some free variable inside the function body like something, it may resolve to the variable defined in its closure other than the one defined in window.
Actually, what I need to do now is to do some manipulations based on the func that has been passed to my function. I can use JSLint to get the undeclared variable. But I also need to resolve these variables. It is acceptable that I can only resolve variables in global scope. But I still need a way to make sure that resolving these variables in global scope is correct. So I need to detect closures.
Is it possible to do that programmatically in javascript?
Alright this is really hacky and probably not worth the effort in actually writing unless your linting or something :)
Basically what you're going to have to do to determine if a function is a closure is call func.toString() which will give you the source of the function. You can then parse the function using some sort of parser which determines all the variables of the function func. You also need to determine and track how these variables are defined. In your criteria in op the criteria for it being a closure is having a variable that is defined outside of function scope and outside of window scope (thus closure scope). So if you can find any variables defined outside of these two scopes we've found a closure.
So heres the pseudocode of hasClosure(), have fun implementing.
func hasClosure(func)
source = func.toString(); //eg "function x(a) {return new Array(a)}"
variables = parseJSForVariables(source)//finds a and Array
for variable in variables:
if(variable not in window)
if(variable not defined in function)
return true //we got a closure
return false //not a closure
The correct answer highly depends on what a "closure" means in this context. The function from the question does not use the variables from the outer scope so, roughly, closure is not created for this function. But strictly speaking, closure is created for any function and binds definition context with the function. So whatever you want to detect, it requires a detailed specification.
But I can assume that the closure here means whether the function references variables declared in outer scope (just like https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures specifies). One of the static for analysis libraries can be used for this. For example, JSLint reports used but undeclared variables. Assuming that undeclared variables are just from the upper scope, this indicates that closure is created.

An object constructor that takes parameters but has no "vars" inside the constructor body, where is the data?

Where is the data supplied by the argument being stored? Is a var first being created implicitly?
function Student(first){
this.getFirst = function(){
return first;
}
}
Tested with:
var myStudent = new Student("ross");
console.log(myStudent); // Student { getFirst=function() }
console.log(myStudent.getFirst()); // ross
console.log(first); // reference error, first not defined
console.log(myStudent.first); // undefined
for(var x in myStudent){
console.log(x);
} // getFirst
My second question is if I understand these correctly:
What happens with "var" variables inside a JavaScript Constructor?
“var” variables, "this" variables and "global" variables - inside a JavaScript Constructor
...is the getFirst function creates a closure and saves the state of the constructor's parameter value, if I use a var first in the constructor body is it okay to think of that as 'encapsulation'? Additionally, any inner function saves all the parameter values in a "closure state" or just the one's referenced by the inner function?
Thank you very much for your thoughts. This is my first question on S.O. but use the site almost daily as a reference, so thank you for that. My programming knowledge is limited so pardon if I've used crappy terms, happy to clarify where needed.
The first parameter is stored locally to the function that is your constructor, so anywhere inside Student() it will be in scope.
More interestingly, the the anonymous inner function that you're assigning to this.getFirst is closing over that value. Because of that, the inner function maintains a reference to the first variable even after the constructor is finished executing.
This works for regular functions too, not just constructors:
function makeCounter() {
var count = 1;
return function() { return count++; };
}
var counter = makeCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
When used the right way, this approach can be used to achieve "private" variables in JavaScript, in the sense that the values captured in the closure are inaccessible from the outside.
Because of that, it turns out not to matter whether a closure captures all the variables in its scope or just the ones it uses, since you can't "reach inside" to those closed-over variables anyway. (Though in practice generally only the used values are captured, so that the runtime can garbage collect the rest, as they're unneeded.)
To get a little further into what you're asking, it's not about creating a var, but rather in your instance the function also keeps the arguments array.
Your functions can happily create closures over both.
By returning functions from your function, those returned functions (or objects with functions as methods) have access to any and all vars and arguments, as long as you don't overwrite those functions.
The magic of closures.

Javascript Closures

I'm quite still confused with the concept of closure in JavaScript. I get the point that closure is the ability of the inner function to access the variable created within its mother function after the mother function has returned.
But I'm still confused why do we have to create inner function to protect the local variable if we could just create a variable inside the function?
We need to create an inner function so that the variables in the outer function have some existence after the outer function returns.
Consider a simple function:
function f() {
var x = 0;
return ++x; // x=1
} // Once the function has exited then "x" no longer exists.
Note that the variable "x" is only "active" (alive, existent) when control of the program flows from the start of the "f()" function to the end of it. But if we enclose "x" in an inner function then x will live as long as the inner function does:
function g() {
var x = 0;
return function() {
// Now "x" will live for as long as this function.
return ++x;
}
};
var counter = g();
counter(); // => 1
counter(); // => 2
counter(); // => 3
Now when we call "g()" we get another function, and "x" is active for as long as that function is referenced by a variable.
Why use closure?
(function(){
var current_page = 1;
function previous_page() {
current_page--;
// update interface
}
function next_page() {
current_page++;
// update interface
}
// a bit of jQuery, ok?
$('#previous').click(previous_page);
$('#next').click(next_page);
})();
Look: we have no global variables, not even any function defined in the global space... yet, we have attached a behaviour to the click events of "#previous" and "#next" buttons for a paging feature. How would you do it without closures? How would you do it defining current_page variable inside the functions?
You just answered your question, the inner function protects it's variable. jsFiddle
(function outer(){
var foo = 'bar';
function inner(){
var foo = 'OMG NO!';
}
alert(foo);//alerts 'bar'
})()
FROM MDN CLOSURES
why to use:
A closure lets you associate some data (the environment) with a function that operates on that data. This has obvious parallels to object oriented programming, where objects allow us to associate some data (the object's properties) with one or more methods.
when not to use
It is unwise to unnecessarily create functions within other functions if closures are not needed for a particular task as it will negatively affect script performance both in terms of processing speed and memory consumption.
For instance, when creating a new object/class, methods should normally be associated to the object's prototype rather than defined into the object constructor. The reason is that whenever the constructor is called the methods would get reassigned (that is, for every object creation).
The reason you need to create the inner function with scoped variables is object oriented encapsulation. It's essentially private variables.
The variables are "closed over".
// constructor function
var myObject = function(message) {
// private - scope is function level. It's CLOSED OVER the the inner function (closure).
// not delcared as a JSON property so not visible externally
var value = 0;
// constructor returns JSON object with public methods
// always constructed from the myObject var so it always hands back the same instance
// of the public methods
return {
// nested functions have access to outer function variables.
increment: function (inc) {
value ++;
},
getValue: function() {
return value;
},
// the inner function even has access to the outer function's args!
getMessage: message
}
};
Look at the return statement. It returns the public interface - some methods that have access to the private variable because they are in the inner function. It's using JavaScripts function scoped variable to create object oriented encapsulation.
After that I can it like:
var obj = myObject('Hello World');
obj.increment();
obj.increment();
console.log(obj.getValue());
console.log(obj.getMessage);
// should be undefined
console.log(obj.value);
Note at this point the consumer does not have access to the protected/encapsulated value or message.
Now, here's the kicker - the object is mutable so the caller can add methods or even replace methods. So, you would think someone could add a method that exposes the internals. But, they can't because of function scope (closure - they're closed over). Only the nested function has access to the variables of the outer function. So, if the caller adds a method to return the internal, they can't get access and it will be undefined.
The code above outputs:
2
Hello World
undefined
As a side note, I'm running the javascript with node.js
Here's a good blog post on the module pattern using closures:
http://www.yuiblog.com/blog/2007/06/12/module-pattern/
The point is that the variable is shared between the two functions. If you declared the variable in the inner function, then the outer function would not be able to access it, so it wouldn't be shared.
If you declared the variable in the inner function, then each call to the inner function would create a new variable: any modifications made by a previous call are lost.
But if the variable is declared in the outer function then multiple calls to the inner function would see the same variable and one call would see the modifications of a previous call so long as they were both scoped to the same version of the outer function.
There are alot of right answers out there about closures, but it always seems to get really technical while many people asking might be looking for a higher level simple explanation first.
I like to think of it like a car. When you drive a car, there are many many complex processes going on, but the average person doesn't need to know about these on an average day. Think of all those complexities as "private" variables hidden away by closures which makes the gas pedal, the break, the shifter, the steering wheel, and so on a lot easier to use.
So what is the purpose of a closure? To hide away all the complex variables and such to make a script much more usable. If you had to worry about every variable in a script everytime you wanted to use any function in the script, well that could quickly get very difficult. YAY CLOSURES!

how does memory stacks work in javascript

When we have code like:
function a(){
var x =0;
this.add=function(){
alert(x++);
}
}
var test = new a();
test.add(); // alert 0
test.add(); // alert 1
test.add(); // alert 2
How does this work?
Doesn't that the value of 'x' in a() should be 'gone' as soon as test = new a() is complete? The stack contains x should also be gone as well, right? Or, does javascript always keep all the stacks ever created in case they will be referenced in future? But that wouldn't be nice, would it...?
The word you're looking for is “closure”.
Creating a function inside another function gives the inner function a (hidden) reference to the local scope in which the outer function was running.
As long as you keep a copy of your test, that has an explicit reference to the add function, and that function has an implicit reference to the scope created when calling the a constructor-function. That scope has an explicit reference to x, and any other local variables defined in the function. (That includes the this value and the constructor's arguments — though you can't access them from inside add as that function's own this/arguments are shadowing them.)
When you let go of test, the JavaScript interpreter can let go of x, because there's no way to get a reference back to that variable.
What you're seeing is the effect of a closure. The function being defined within the other function gets access to all of the variables and such in scope where it is — even after the outer function returns. More here, but basically, the variables (and arguments) in the function all exist as properties on an object (called the "variable object") related to that function call. Because the function you've bound to this.add is defined within that context, it has an enduring reference to that object, preventing the object from being garbage-collected, which means that that function can continue to access those properties (e.g., the variables and arguments to the function).
You normally hear people saying that the function closes over the x variable, but it's more complex (and interesting) than that. It's the access to the variable object that endures. This has implications. For instance:
function foo() {
var bigarray;
var x;
bigarray = /* create a massive array consuming memory */;
document.getElementById('foo').addEventListener('click', function() {
++x;
alert(x);
});
}
At first glance, we see that the click handler only ever uses x. So it only has a reference to x, right?
Wrong, the reference is to the variable object, which contains x and bigarray. So bigarray's contents will stick around as well, even though the function doesn't use them. This isn't a problem (and it's frequently useful), but it emphasizes the underlying mechanism. (And if you really don't need bigarray's contents within the click handler, you might want to do bigarray = undefined; before returning from foo just so the contents are released.)

Categories