I have read number of answers in SO, however I cannot come up a clear explanation in my mind about variable life time in javascript. Generally answers are about hoisting/shadowing which is not the case here imo. For instance, we often write those kinds of scripts along with jQuery;
function getSomeData() {
var $container = $('#someContainer');
$.get('/url', function(data) {
$container.html(data);
});
}
Now, my main question is how does $container variable remain available to the anonymous callback function? I know, when execution comes up to $.get, get immediately returns and getSomeData returns eventually, though get may return any time in future. Hence I'm forced to think that getSomeData in fact remains in function call stack in order to provide $container variable to callback function, because to my knowledge if a variable is not found in the scope it is used, interpreter looks it up in parent scope (to the global scope). Here are the side questions:
Does this kind of pattern causes performance degradation?
If I change anonymous function to a declared function and use like;
var callback = function(data) {
$container.html(data);
}
$.get('/url', callback);
is there any advantage of this usage (except for debug purposes, and readability)?
If there is no function call stack involving here, where is $container stored until the promise resolves? Plase note that also this nesting is possible:
function getSomeData() {
var $container = $('#someContainer');
var replaceHtml = function(data) {
$container.html(data);
}
$.get('/url', function(data) {
replaceHtml(data);
});
}
Please give a clear explanation of that, thanks!
Now, my main question is how does $container variable is available to anonymous callback function?
...Hence I'm forced to think that getSomeData in fact remains in function call stack in order to provide $container variable to callback function, because to my knowledge if a variable is not found in the scope it is used, interpreter looks it up in parent scope (to the global scope).
You're really close to understanding this. Just a couple of corrections and clarifications will get you there.
It has nothing to do with the function call stack. You're quite right that getSomeData returns before the callback is run. That means it comes off the stack, just like normal. However, its local variables and such
live on, even though the function has returned. Why? Because the callback has an indirect reference to them.
When a JavaScript function is called, an object is created (theoretically) which is the execution context for that call. That context contains a variety of things, including an object called the variable environment that contains the arguments and variables and such related to the call. Any function created within the context keeps a reference to that context's variable environment object, and so has access to them even though the function has returned. These functions are called closures because they "close over" the context in which they were created.
So when the callback refers to the $container variable, the JavaScript engine looks in the callback's own context and its variable environment and, not finding $container there, looks at the next containing environment. It finds $container there and uses it.
Let's break it down into steps. Please note there's hand-waving here, the spec contains the details.
Something calls getSomeData
The engine pushes the return address on the stack
The engine creates an execution context for the call
The engine creates a variable environment for the context, populating it with the arguments, local variables, etc.
The engine runs the code in the function
Part of that is creating the callback function, which is given a reference to the variable environment object
Another part is handing that function reference to $.get, which keeps it for a while
Code exectuion "falls off" the end of the function, so the engine pops the return address from the stack and carries on
Some time later, $.get calls the callback through the reference to it that it kept
A new context and variable environment are created for the call to the callback
Callback code runs, looking up things in its own variable environment and also the environment in which it was created (for $container)
Code execution "falls off" the end of the function, the engine pops the stack, $.get drops its reference to the function
Since the function has nothing referring to it, it's eligible for garbage collection
At some point, the engine's GC algorithm disposes of the function, and so the function no longer refers to the variable environment object from the call to getSomeData, and so that object is eligible for GC.
At some point, the engine disposes of the variable environment object
Now, other than side-effects (like actually using the information from $.get), all is cleaned up
Does this kind of pattern causes performance degradation?
Not in and of itself, no. If you create a function and keep it around, then since it keeps the variable environment where it was created around, that can cause memory impact. But once you release the function (in this case, once $.get has called it and dropped its reference to it), then the function can be GC'd, and the variable environment (and its contents) can be GC'd.
In the above I talk about a lot of objects and garbage collection, but of course JavaScript engines can and do a lot of optimization around this. It's a big part of why modern engines are so much faster than the old ones were. (Just one part, but part.)
If I change anonymous function to a declared function and use like;
var callback = function(data) {
$container.html(data);
}
$.get('/url', callback);
is there any advantage of this usage (except for debug purposes, and readability)?
No.
If there is no function call stack involving here, where is $container stored until the promise resolves?
See above.
Related
I have two questions about hoisting:
The way function declarations are hoisted is that they go to the very top, even above variable declarations, to my understanding.
If we have this code:
function fn() {
callback();
}
function callback() {
console.log('why does this show');
}
I don't understand how this works, since both functions are hoisted to the top (which effectively produces the same code that already exists). But callback is still created below fn, and I don't see why we can access it in fn. My guess is it has something to do with the top level objects being able to access each other regardless of lexical position.
Similarly:
var a = 10;
function fn() {
console.log(a);
}
fn();
How does this work? Because the way I understand hoisting makes it seem like the function should be hoisted even above var a, which makes it seem like variables should always be inaccessible in functions.
We can go down the rabbit hole with this but I want to try to give a brief explanation on how your examples work.
Whenever the JavaScript engine creates an execution context (also known as calling stack) whether through functions or code in the global scope it creates an lexical environment. Which is a data structure that holds a collection of name/value pairs about variables and functions in it's own scope or from it's parent scope by using a reference.
About your first example. Both functions get added to the global execution context. If you call fn() in your first example initially. It will then add callback() to the call stack of fn() and execute it accordingly. So, the order of your functions don't really matter in this case.
You're second example is a different case. The execution context knowns you are referring to the global variable and therefor adding a reference to the lexical environment and that makes it able to use the variable inside fn().
This can be quite hard to get a grasp of. There are a ton of resources related to hoisting, scopes, lexical environments and execution contexts so be sure to check those out. :)
This is because how our Javascript Engine parse and compile the code.
I'm not an expert but V8 (The Chorme Engine for JS) in the first file get all the variables and functions names and store all the function references. So, you can "use" a function before "declare" because JS know where the function is.
Some languages, even C++ you could do that and is a nice feature :)
If have a callback that is activated repeatedly such as the following...
Template.foo.rendered = function() {
$(this.firstNode).droppable({
// other arguments
drop: function() {
// some really long function that doesn't access anything in the closure
}
});
}
Should I optimize it to the following?
dropFunction = function() {
// some really long function that doesn't access anything in the closure
}
Template.foo.rendered = function() {
$(this.firstNode).droppable({
// other arguments
drop: dropFunction
});
}
In this case, the rendered callback is a Meteor construct which runs asynchronously over a DOM node with template foo whenever they are constructed; there can be quite a few of them. Does it help to declare the function somewhere in a global closure, to save the Javascript engine the hassle of keeping track of an extra local closure, or does it not matter?
I don't believe that in modern browsers that there will even be a difference. When creating a closure object, V8 determines what variables your function uses, and if you don't use a variable it won't put it in the closure object(I read this somewhere online a while back, sorry I can't find the link*SEE BELOW*). I assume any browser that compiles JavaScript would do the same.
What will be optimized is the creation of the function. In the second example the drop function is created at the same time as the rendered function, in the first it's re-created every time the rendered is called. If this was in a long for loop that might be worth optimizing.
I personally think the first example is a lot easier to read and maintain. And as I said in a comment on the question you(or the person editing this code in the future) could accidentally overwrite the function variable(in an event handler or something) and you could have a hard to find bug on your hands. I would suggest saying with number 1, or wrapping everything in a self-executing function so dropFunction has a smaller scope and less chance of being overwritten, like so:
(function () {
var dropFunction = function() {
// some really long function that doesn't access anything in the closure
}
Template.foo.rendered = function() {
$(this.firstNode).droppable({
// other arguments
drop: dropFunction
});
}
})();
EDIT: I found the link, it was actually in a blog post about a closure memory leak in Meteor!
http://point.davidglasser.net/2013/06/27/surprising-javascript-memory-leak.html
Here's the portion I mentioned:
JavaScript implementations (or at least current Chrome) are smart enough to notice that str isn’t used in logIt, so it’s not put into logIt’s lexical environment, and it’s OK to GC the big string once run finishes.
I'll start this by saying I don't know anything about meteor :/ but if I'm understanding what happens correctly, basically:
Template.foo.rendered
Gets called repeatedly. When that occurs, you construct and object + define a new function on it "drop" which is eventually invoked. If that is the case, you are better off from a performance perspective defining drop once at parse time. But the benefit probably depends on how often rendered is called.
As for why - I posted something similar here:
Performance of function declaration vs function expressions in javascript in a loop
And I think #soktinpk's answer I think is a great summary.
If you look at the jsperf in the above link it may not initially seem directly applicable, but if my assumed statements above are true it is in fact is - because the question at hand boils down to how expensive is to define a function at runtime vs parse time and are you defining this function at runtime over and over again.
If you look at the performance of the loops where a function is defined at runtime vs the loops where functions are defined at parse time (or defined at parse time and hoisted), the parse time loop run significantly faster.
I believe that the equivalent of what meteor is doing in your example is probably something like this jsperf: http://jsperf.com/how-expensive-is-defining-a-function-at-runtime2
What I have done here is created two loops that simulate your scenario being invoked over and over again. The first invokes a function that creates and object and function and passes it to another function for invocation.
The second creates and object that references a function and passes it to another function for invocation. The difference in performance looks significant (58% in chrome).
I'm making headway on understanding closures, but I don't understand how the following example even creates a closure. I'll quote a passage from 'Learning jQuery', page 392, and what the author says about the example.
The author says that because "readyVar persists between calls to the function", we can see a closure is involved. But, to me, readyVar persists between calls to innerFn simply because the anonymous function has not yet finished executing. Once the anonymous function finishes, there will be no references to readyVar and it will be garbage collected. So where is the closure? I'm under the impression that a closure involves a variable being referenceable in a scope outside of that scope in which the variable was defined. But I don't see that here.
Is the author saying that anytime an inner function references a value defined in an outer function, a closure is created? That can't be what he's saying, can it?
The rest of this message is a quotation from the aforementioned book.
$(document).ready(function() {
var readyVar = 0;
function innerFn() {
readyVar++;
$('#example-9').print('readyVar = ' + readyVar);
}
innerFn();
innerFn();
});
This looks like many of our earlier examples, except that in this case, the outer function is the callback passed to $(document).ready(). Since innerFn() is defined inside of it, and refers to readyVar which is in the scope of the callback function, innerFn() and its environment create a closure. We can see this by noting that the value of readyVar persists between calls to the function:
readyVar = 1
readyVar = 2
For the duration of the $(document).ready function, all it's local variables are active and hold their values and any code in that function or any embedded functions can reference them. While one could describe this as a function closure, this is more just how local variables work in a function.
If, inside the $(document).ready, there was an embedded function that stored a reference somewhere (like a click handler), then a lasting function closure would be established and the value of readyVar would last as long as any embedded references last. It's essentially garbage collection. As long as something outside the function loop holds a reference to something inside the loop, the loop stays alive. At the point where the loop is done executing and nothing outside the loop holds any embedded function references to things inside the loop, the loop gets garbage collected and goes away.
Since there are not embedded function references in what you have now, it will get garbage collected (e.g. destroyed and freed) when it finishes executing.
Now, if you modified it to add a click handler like this, then you now have a lasting reference to a function inside the $(document).ready function with the click handler function. Since that lives on, even after the $(document).ready loop has finished executing, it will not be garbage collected and will live on as a function closure.
$(document).ready(function() {
var readyVar = 0;
function innerFn() {
readyVar++;
$('#example-9').print('readyVar = ' + readyVar);
}
innerFn();
innerFn();
$("#content").click(function(){ // external reference to within this function
alert(readyVar);
});
});
I sense from your question that you're confusing local variables with function closures. The two are related, but not the same thing. Local variables are always available for the lifetime of the function. The lifetime of the function is the time it's executing except when a reference to a closure within it causes it to last longer than that.
You might find this helpful: http://blog.morrisjohns.com/javascript_closures_for_dummies.html
I'm having a little difficulty with the inherent concept of a closure. I get the basic idea, but here's the thing: I thought that, technically, there "is a closure" inside every Javascript function. To quote wikipedia:
In computer science, a closure (also lexical closure, function closure
or function value) is a function together with a referencing
environment for the nonlocal names (free variables) of that function.
Such a function is said to be "closed over" its free variables.
So since you can define variables inside a function, they are "closed off" to the rest of your code, and so I see that as a closure. Thus, as I understand it:
(function(){var a = 1;}())
Is a (not very useful) example of a closure. Or heck, even just this:
function(){var a = 1;}
But, I think my understanding might be wrong. Others are telling me that for something to be a closure it has to persist a state, and so since nothing persists beyond that code it's not really a closure. That suggests that you need to have:
function(foo){foo.a = 1;}(bar); // bar.a = 1
or even (to ensure un-modifiability):
function(foo){var a = 1; bar.baz = function() { return a}}(bar); // bar.baz() = 1
So, technically speaking (I know several of the examples are practically speaking pointless, but) which of the above examples are actually examples of closures. And does a closure just have to be a space (ie. inside a JS function) where variables can be stored that can't be accessed form outside, or is persistence a key part of a closure's definition?
EDIT
Just noticed the wiki definition for the "closures" tag on Stack Overflow:
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.
While the SO wiki is certainly no final authority, the first sentence does seem to correlate with my understanding of the term. The second sentence then suggests how a closure can be used, but it doesn't seem like a requirement.
EDIT #2
In case it isn't clear from the varying answers here, the wikipedia answer, and the tag answer, there does not seem to be a clear consensus on what the word "closure" even means. So while I appreciate all the answers so far, and they all make sense if you go with the author's definition of closure, what I guess I'm really looking for is ... is there any actual "authoritative" definition of the word (and then if so, how does it apply to all of the above)?
You're being led astray by a wrong assumption of where the word "closure" comes from.
In a language-theoretic context, the point of a closure is that the function can refer to variables declared outside its own definition. It is immaterial whether it has internal variables, or that the internal variables are not visible from outside. In other words it is about seeing out from the function to its definition environment, not about seeing in from outside the function.
Why the weird word, then? Look at the function in your last example:
bar.baz = function() { return a }
This function contains a mention of the variable a which is not defined in the function body itself. It is a "free" variable of the function body, sort of a "hole" in the definition. We cannot execute the function without knowing, by some extraneous means, what variable the identifier a in the body refers to. Forming a closure at run-time pairs this "open" function body with a reference to the appropriate variable, thereby closing the hole in the definition. And that's where the name comes from.
(If you want the completely technical explanation, the underlying concept is that of a "closed" term in the lambda-calculus, which means one that has no free variables. Only closed term have independent meanings. A closure is then the combination of a (usually compiled) non-closed piece of source code, together with the contextual information that lets it behave like it was a closed term, and therefore be executable).
Addendum: In the common idiom
function() {
var blah;
// some code here
}();
the point is not to get a closure (you will get one, of course, but it doesn't do anything interesting for you), but to create a local scope for the blah variable. A local scope is conceptually quite a different thing from a closure -- in fact most C-lookalikes other than Javascript will create them at every {} block, whereas they may or may not have closures at all.
None of your samples are closures technically speaking. (But forth sample can be classified as such in some circumstances, see below)
Closure is a data structure that combines reference to a function and non-empty list of call frames (or scopes) active at the moment of declaration.
Closure is created by executing some code that contains declaration of a function that uses variables from outer scopes. In this case runtime, while executing the code, has to create not just a reference to the function but closure structure - function reference and reference to its current environment - list of call frames that hold used outer variables.
For example in my TIScript call frames are replaced on stack - when you exit from a function its call frame that includes collection of variables it uses is purged from the stack. Closure creation in my case happens when: VM meets function declaration instruction and that function is marked (by compiler) as the one that uses outer variables. In this case current chain of call frames that hold used variables is moved from stack to the heap - converted to GCable data objects and reference to the function and its call chain is stored as a reference.
Your fourth case physically does not require closure to be created - no need to store call frames for later use - bar.baz contains just a number - not a reference to function.
But this:
function(foo){
var a = 1;
bar.baz = function() { return a; };
}
creates closure in bar.baz field. When you later invoke bar.baz() function code is executed and value of 'a' variable will be taken from reference to outer call frame that is stored in closure.
Hope it clears something for you.
Closures in JavaScript (and other languages) are used to control and define scope. There's no requirement that you define a function within a function for it to "qualify" as a closure. The body of a function is a Closure. One of the more common uses is to declare a local scope variable that becomes a Private or Hidden member of some other object or function you'll return, but that's not a hard-fast rule.
i am wondering if i can do some cleanup routines that will auto grab timeouts / intervals. consider this:
var timeout = setInterval(function dimitar() {
console.log("hi!");
}, 1000);
console.log(window);
i had a look through window and can't find any reference to the function that's been passed on. the reference to timeout is there, sure enough. so where does the function 'live' here? is it launching a new instance of the js interpreter to eval/run/keep the code? how can you access it in relation to the timeout uid?
i know i can curry the setInterval function and get it to always store the reference into an array which i can then loop through and clear, but am curious if there's a natural way of doing this
The function you create in your example is using a named function expression. The name is only available within the function. Otherwise, it behaves the same as an anonymous function: you haven't assigned it to a variable and since it's not a function declaration, it doesn't create a dimitar variable in the enclosing scope. The following article may be useful: http://yura.thinkweb2.com/named-function-expressions/
There's no eval-type thing going on: you've just passed in a reference to a function into window.setInterval. This function cannot be retrieved afterwards unless you've assigned it to a variable previously, or it was a reference to a function defined by a function declaration.
If you want to keep a reference to the function around, it's simply a matter of storing it in a variable first:
var dimitar = function() {
console.log("hi!");
};
window.setInterval(dimitar, 1000);
so where does the function 'live' here?
The timeout/interval queue is an internal implementation detail that's not accessible to content JavaScript. It retains a reference to the function passed in to setInterval, but it's not a reference that's visible to you.
Incidentally you should generally avoid using named inline function expressions. Although it's probably OK in this example code, IE's JScript has some serious basic bugs with them that can trip you up if you're not careful. Stick to named function statements (function dimitar() { ... } ... setInterval(dimitar, 1000)) or anonymous inline function expressions (setInterval(function() { ... })).
is it launching a new instance of the js interpreter to eval/run/keep the code?
No, it's the same interpreter and the queue could even be implemented in JavaScript. But the variables behind it are hidden away from the caller.
how can you access it in relation to the timeout uid?
The timeout ID is by design completely opaque. The only defined interface that can do anything with it is the clearTimeout/clearInterval call. There is no interface provided to get the function back from a timeout ID.