问题
My question is based on the example from a book "Object Oriented JavaScript" (page 81 - Lexical Scope)
So, i understand from this example ...
function f1(){var a = 1; f2();}
function f2(){return a;}
f1();
... that:
a is not defined
But, how f1 get's to know about f2, which is defined after f1 ?
This behavior raises a question:
How JavaScript interpreter works ?
I assume, that it:
- scans the code and simply stores the functions, not assigned to any var, in a global environment
- Invokes a function in ad-hoc way: when there is no such a function in a global environment, then complain.
回答1:
Function declarations are processed upon entry into an executable context (e.g., the global context, or a function call), prior to any of the step-by-step code in the context being processed.
So in your code, these things happen (in this order):
- A "variable object" is created for the execution context.
- Entries (actually, literally, properties) on the "variable object" are created for every
var
and function declaration in the context (plus a few other things). In your case, that'sf1
andf2
. Initially the properties have the valueundefined
. - All function declarations are processed, and so:
- The
f1
function is defined and assigned to its property on the variable object. - The
f2
function is defined and assigned to its property on the variable object.
- The
- The
f1();
line is executed, calling thef1
function. - The
f1
code refers tof2
, which it gets from the variable object, and so it's what we expect it to be (a reference to thef2
function).
The more interesting version is this:
f1();
function f1(){var a = 1; f2();}
function f2(){return a;}
...which happens in exactly the same order listed above, because both of the declarations are handled before the first line of step-by-step code.
Function declarations are different from function expressions, which just like any other expression are evaluated when they're reached in the step-by-step execution of the code. A function expression is any time you create a function and use it as a right-hand value, e.g., assign the result to a variable or pass it into another function. Like this:
var f2 = function() {
};
or this
setTimeout(function() {
alert("Hi there");
}, 1000);
Note that we're using the result of the function
statement as the right-hand value (in an assignment, or by passing it into a function). Those are not pre-processed upon entry into an execution context (e.g., not at Step 3 above), they're handled when the flow of code reaches them. Which leads to:
f1();
function f1(){var a = 1; f2();}
var f2 = function(){return a;};
...which fails, because f2
is undefined as of when it's called.
You can use a declared function's value as a right-hand value without turning it into a function expression (we do that all the time), so long as you do it in two separate statements. So:
alert("Beginning");
function foo() { ... }
setTimeout(foo, 100);
That happens in this order:
foo
is created (since it's defined by a declaration).- The
alert
runs. - The
setTimeout
runs. - (Later)
foo
is called.
One last point: Although they should work, a function expression that includes a function name does not work reliably on all implementations and must, for now, be avoided:
var f = function foo() { ... }; // <== DON'T DO THIS
Or
setTimeout(function foo() { // <== DON'T DO THIS
}, 1000);
Internet Explorer, in particular, has issues with those, and other implementations have at various times as well.
More to explore:
- Poor misunderstood var
- Closures are not complicated (because it talks about variable objects and how symbols are resolved)
- Anonymouses anonymous (talks more about named function expressions)
回答2:
you don't have access to variable 'a' inside function f1, because function f2 is not defined inside f1 scope
if you define f2 inside f1:
function f1(){function f2(){return a;} var a = 1; f2();}
f1();
you don't have any problems
来源:https://stackoverflow.com/questions/4518312/order-of-functions-in-javascript