我的问题是基于“Object Oriented JavaScript”一书中的例子(第81页 - 词汇范围)
所以,我从这个例子中理解......
function f1(){var a = 1; f2();}
function f2(){return a;}
f1();
...那:
a未定义
但是,f1如何了解f2?f2是在f1之后定义的?
这种行为引发了一个问题:
JavaScript解释器的工作原理?
我认为,它:
答案 0 :(得分:16)
在进入可执行上下文(例如,全局上下文或函数调用)之后,在处理上下文中的任何逐步代码之前处理函数声明。
所以在你的代码中,这些事情发生了(按此顺序):
var
和函数声明创建“变量对象”上的条目(实际上,字面上,属性)(以及其他一些内容)。在您的情况下,那是f1
和f2
。最初,属性的值为undefined
。f1
函数已定义并分配给变量对象的属性。f2
函数已定义并分配给变量对象的属性。f1();
行,调用f1
函数。f1
代码引用f2
,它是从变量对象获取的,因此它是我们所期望的(对f2
函数的引用)。更有趣的版本是:
f1();
function f1(){var a = 1; f2();}
function f2(){return a;}
...发生在上面列出的完全相同的订单中,因为两个声明都是在第一行逐步代码之前处理的。
函数声明与函数表达式不同,它们就像在逐步执行代码时到达任何其他表达式一样进行评估。函数表达式是指您创建函数并将其用作右侧值时,例如,将结果赋值给变量或将其传递给另一个函数。像这样:
var f2 = function() {
};
或者
setTimeout(function() {
alert("Hi there");
}, 1000);
请注意,我们使用function
语句的结果作为右侧值(在赋值中,或通过将其传递给函数)。那些在进入执行上下文时(例如,不在上面的步骤3中)不进行预处理,它们在代码流到达它们时被处理。这导致:
f1();
function f1(){var a = 1; f2();}
var f2 = function(){return a;};
...失败,因为f2
在调用时未定义。
您可以将声明函数的值用作右手值而不将其转换为函数表达式(我们始终这样做),只要您在两个单独的语句中执行它。所以:
alert("Beginning");
function foo() { ... }
setTimeout(foo, 100);
按此顺序发生:
foo
已创建(因为它是由声明定义的)。alert
运行。setTimeout
运行。foo
被召唤。最后一点:虽然应工作,但包含函数 name 的函数表达式在所有实现上都不能可靠地运行,并且现在必须避免:
var f = function foo() { ... }; // <== DON'T DO THIS
或者
setTimeout(function foo() { // <== DON'T DO THIS
}, 1000);
特别是Internet Explorer存在问题,其他实现也有不同的时间。
更多探索:
var
答案 1 :(得分:0)
您无法访问函数f1中的变量'a',因为函数f2未在f1范围内定义
如果在f1中定义f2:
function f1(){function f2(){return a;} var a = 1; f2();}
f1();
你没有任何问题