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.)
Related
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.
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.
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.
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!
It is said, javascript clears a variable from memory after its being referenced last.
just for the sake of this question i created a JS file for DEMO with only one variable;
//file start
//variable defined
var a=["Hello"]
//refenence to that variable
alert(a[0]);
//
//file end
no further reference to that variable, so i expect javascript to clear varaible 'a'
Now i just ran this page and then opened firebug and ran this code
alert(a[0]);
Now this alerts the value of variable, If the statement "Javascript clears a variable after there is no further reference it" is true how come alert() shows its value.
Is it because all variable defined in global context become properties of window object, and since even after the execution file window objects exist so does it properties.
Of course the variable HAS to be kept around in this example - after all, you keep the ENVIRONMENT it has been defined in around. As long as you COULD still access it is has to be kept, so if you can make this test and it ever fails - the JS interpreter is "kaputt".
Do this instead:
(function () {
var a = 1;
}());
// and NOW, at THIS point there is nothing any more referencing "a"
Of course, from out "here" you cannot test that - you'd have to look at the internal memory structures of the JS interpreter/compiler (today in the days of V8 it's more like a "interpiler" or "compreter" aynway).
In addition though, like all garbage collecting (GC) languages, the memory is not freed immediately but depending on GC strategy used by the particular implementation of Javascript, which also takes current memory usage and demand into account. GC is a costly operation and is delayed, if possible, and/or run when it does not take away CPU resources from the real app.
By the way, slight variation:
(function () {
var a = 1;
//empty function assigned to global namespace,
//in browsers "window" is the global object
window.example_function = function () {};
}());
In THIS example the result is the same as in yours: as long as you view that page the memory for "a" is NEVER released: the function assigned to property example_function of the global object still exists, so all of the environment is was defined in has to be kept! Only after
delete window.example_function
which deletes that property - which in the end is a pointer to the (empty) function expression - from the global object, could variable "a" be released. Also note that "a" is not even used by that function, see Google and search for "lexical scoping", one of the most defining properties of the Javascript language.
And even more fun:
Had I written
//define a variable in global namespace
var example_function;
(function () {
var a = 1;
//empty function assigned to global namespace,
//in browsers "window" is the global object
example_function = function () {};
}());
I could not use "delete" to remove it, in fact I could not ever release it. That's because in the first example example_function becomes a new property of the global object (emphasis), while in this last example it is a variable, and "delete" works with object properties only. (I used "windows.example_function" in the earlier example, but without the "window." it would have been just the same, example_function would have been created as property in the global object. Only the "var" statement creates variables.)
Is it because all variable defined in global context become properties of window object, and since even after the execution file window objects exist so does it properties.
Yes. You would either have to close the window, or explicitly remove a from the window properties.
A side effect of your script is that there's a property name "a" defined in the global object ( window ), so there is actually still a global reference to a.
(function()
{
var a = 12;
alert(a);
})();
If we wrap the declaration of a in self-executing function like here, a will be inaccessible after the function has exited.
Yes, although you can mitigate this behavior by declaring and acting on your variables within the scope of a function:
( function myfunc(a){
var b = 100;
alert(a); // 200
alert(b); // 100
}(200));
alert(a); // undefined
alert(b); // undefined
Referencing a variable does not mean using it in some manner. As long as there is at least one reference to the variable which can still be accessed, it has to be kept in memory.
Looking at your example, the following line has no effect on whether the variable gets cleared or not. Even if a wasn't being used anywhere, it would still have been kept intact.
//refenence to that variable
alert(a[0]);
Although an object may be created inside a function, its lifetime may extend beyond the function itself. The only thing to remember is whether there are still any valid references to the object in question. Consider this example,
(function() {
var a = ["Hello"];
var copy = a;
a = null;
setTimeout(function() {
// a: null, copy: ["Hello"]
console.log("a: %o, copy: %o", a, copy);
}, 2000);
})();
The variable a is created inside an anonymous function, and another variable copy is referencing it. a is set to null right after, but we still have 1 reference to it from copy. Then we create a timeout which makes another reference to the same variable. Now even though this anonymous function will go out of scope after it executes the setTimeout, we still left 1 reference to it in the timeout function. So this copy variable will still be intact when the timeout function is run.