I don't understand this example of a closure
Crockford had this example to keep myArray from being in the global scope:
var myName = (function() {
var myArray = ['zero','one','two','three','four'];
return function(X) {
return myArray[X];
}
}()); // This function is invoked immediately
result = myName(3); // Now invoke it "for real"
Q: I don't get why it isn't
var myName = (function(X) {
Q: When I call myName(3), isn't "var myArray=" executed a 2nd time? Suppose it's not executed a 2nd time because JavaScript knows开发者_如何学Python that it's already been defined... What about a loop or some other logic between the var stmt and the return function stmt? Wouldn't it be executed every time?
Q: Can you name the subfunction and call it instead of calling myName?
okay, let's break this down...
var myName = (function(){
...
}());
that piece sets myName
to whatever that anonymous function returns, so if it were:
var myName = (function(){ return 42; }());
myName
would equal 42
. If that doesn't make sense, this is the same thing:
function someFunction(){ return 42; }
var myName = someFunction();
So in your example, myName
is set to function(X){ return myArray[X] }
. So myName is a function. When you call it, the only code that is run is return myArray[x]
. myArray
is kept in what is called a closure, it is only exposed to the myName
function and the anonymous one surrounding it.
I wrote an article on closures years back that may help you: http://www.htmlgoodies.com/primers/jsp/article.php/3606701/Javascript-Basics-Part-9.htm (scroll down to the "Closures" header).
OK here it goes .. answer to Q1 . it is not myName = (function(x) because the part inside the brackets returns a function which takes X . i.e. myname is not assigned to (function(){}) but to the return value of it .
Q2. No when u calll myName 2nd time it already points to the inner function hence the outer function is not invoked at all .(this is the sepciality of closures where the value stays alive in inner function even if outer functions are completed.)
Q3. Well nopes we can name the inner function but the name will be valid only inside the outer function and since outer function has completed the name would be useless.
The outer function doesn't have to have an argument X
, because it's only purpose is to return another function (which then is parametrized). Thus no argument is needed here.
Thus the only effect is to bind the function(X)...
thing to the variable myName
. Therefore no other constructs like loops or so does make sense here.
Q1+2: Note the ()
right of the comment "This function is invoked immediately". The outer function defined is not stored in myName
, but immediatly called. Itself then returns an anonymous function which has no name and requires a single parameter (X
). This function beeing returned is stored in myName.
To grasp closure you should start thinking about functions just as another value of a variable which can be stored and returned jsut as any other value.
Q3: myName is the subfunction.
Okay answer in turn:
First, why it's var myName = (function() {
and not var myName = (function(x) {
In this case because the x
value isn't required to create the function you are returning. The data structure of the array contained in the returned function is hard coded and so you don't need additional information to construct it. Much in the same way that
function a() {
return 1 + 2;
}
Doesn't have any arguments, because it's values are hardcoded. This is an example of functions as data or first class functions
Question two: is var myArray
executed every time.
The short of it is no. myArray has been assigned to at this point so it has a value that the system has already calculated. In this case it's a function. The myArray potion has been set and so there is no cause to keep executing it. If the outer function didn't return a new function then yes it would need to get called again and again but that would defeat the purpose of this abstraction.
Question three: can you call the inner function.
No, it's out of scope. The entire point of this example is that you have defined a function generator.
Answer to first question: no, the first "line" is returning a function so when you call "myName" you are actually executing the returned function
function(X) {
return myArray[X];
}
Answer to second question
no, such a function can still refer to the array "myArray"... in fact the purpose of this closure is to make myArray available in the global scope
In words:
myName
is the result of an immediately executed anonymous function. It returns a function reference (to an anonymous function). That function has one parameter: X
. After execution of the topmost anonymous function, myName
is a reference to the inner anonymous function.
Now the inner anonymous function has access to myArray
via a closure (myArray
and the returned anonymous function both live within the scope of the topmost anonymous function). So if you execute myName
, you actually execute the inner anonymous function, which can access myArray
.
The topmost anonymous function is executed immediately and once (it returns a reference to the inner function). So myArray
is declared within that execution context, and only once.
Since the definition of the myName object (function) ends in '()', its function is called immediately, returning a new function which has the myArray variable statically bound to it. myName is then accessible globally but myArray is not as it is within a function closure. When you reference myName() it has exclusive access to the bound array.
This approach ensures that myArray is only allocated once, when the outer function 'is invoked immediately'. After it is invoked, myArray isn't in the global scope, but is still available to the anonymous inner function.
The approach you proposed would work, but would require that the array be allocated each time the function was called. (Or be allocated outside the function, in the global scope.)
精彩评论