I decided to make one step forward on trying to understand Javascript and read again Javascript: The Good Parts. And here comes the first doubt:
Let’s say I want to avoid using the global variables because they are evil, and so I have the following:
var digit_name = function(n) {
var names = ['zero','one','two','three'];
return names[n];
}
D.Crockford claims that this is slow because everytime the function gets called, a new instantiation of names is done. So, then he moves to the closure solution by doing this:
var digit_name = function () {
var names = ['zero', 'one', 'two', 'three'];
return function (n) {
return names[n];
}
}();
This makes the names variable stored in memory and therefore it doesn’t get instantiated every time we call digit_name.
I want to know why? When we call digit_name, why is the first line being “ignored”? What am I missing? What is really happening here?
I have based this example not just in the book, but on this video (minute 26)
(if someone thinks of a better title, please suggest as appropriate…)
I’m sure you meant to make your second example function an immediate executing (i.e., self-invoking) function, like this:
The distinction involves scope chain with closures. Functions in JavaScript have scope in that they will look up into parent functions for variables that are not declared within the function itself.
When you declare a function inside of a function in JavaScript, that creates a closure. A closure delineates a level of scope.
In the second example,
digit_nameis set equal to a self-invoked function. That self-invoked function declares thenamesarray and returns an anonymous function.digit_namethus becomes:From your original example, you can see that
namesis declared one up level up the scope chain from the returned anonymous function (which is nowdigit_name). When that anonymous function needsnames, it travels up the scope chain until it finds the variable declared–in this case,namesis found one level up the scope chain.Regarding efficiency:
The second example is more efficient because
namesis only declared once–when the self-invoking function fires (i.e., var digit_name = (function() { … })(); ). Whendigit_namesis called, it will look up the scope chain until it findsnames.In your first example,
namesgets declared every timedigit_namesis called, so it is less efficient.Graphical example:
The example you’ve provided from Douglas Crockford is a pretty tough example to start out with when learning how closures and scope chains work–a lot of stuff packed into a tiny amount of code. I’d recommend taking a look at a visual explanation of closures, like this one: http://www.bennadel.com/blog/1482-A-Graphical-Explanation-Of-Javascript-Closures-In-A-jQuery-Context.htm