Function names defined as parameters to a function call aren't hoisted. Why not?
请考虑以下代码。
1 2 3 4 | <!DOCTYPE html> console.log(a); function a() {} |
请注意,
1 | function a() {} |
函数和变量名称在任何其他代码运行之前定义,因此console.log调用在此处起作用。这称为吊装。
但是,如果函数被定义为函数调用中的参数,则这不起作用。看看这段代码。
1 2 3 4 5 | <!DOCTYPE html> function a() {} a(function b() {}); console.log(b); |
请注意,函数
1 | Uncaught ReferenceError: b is not defined |
我想知道为什么会这样。这是预期的行为吗?这在Chrome和Firefox中都会发生。
更新:此jsfiddle显示函数表达式中的名称在定义它们的作用域中永远不可用。但是,名称是在函数本身的范围内定义的。这意味着命名函数表达式可以引用名称,但仅限于函数内部。该名称也存储在函数的
1 2 3 4 5 6 7 8 9 10 | <!DOCTYPE html> console.log(a); // undefined var a = function b() { console.log(b); // function b() { … }; }; a(); // function b() { … }; console.log(a); // function b() { … }; console.log(a.name); // b console.log(b); // Uncaught ReferenceError: b is not defined |
EcmaScript§13(参见NOTE下面的段落)定义了如何处理函数表达式和函数声明。
函数声明在构建EnvironmentRecord(第10.5节)时被实例化,因此被提升,稍后将对函数表达式进行求值,并且它的可选标识符对于封闭范围永远不可见。
由于这是一个函数表达式,因此外部作用域的名称不可见。它是一样的
1 2 3 4 5 | a = function(){}; // valid as it is a function expression a = function b(){};// also valid // b is is not accessable here, same as the anonymous function, but a of course is. |
两者都有效,但外部范围不可见b。但是,省略函数声明中的名称无效。
函数表达式的可选标识符用于函数体内的参考目的(例如,用于启用递归调用)。
更新到您的更新:
第一个console.log产生undefined而不是抛出错误的原因是提升(虽然实例化已经提升,但初始化不是):
1 2 3 4 5 6 7 8 9 | console.log(a); // undefined var a = function b() {}; console.log(a); // function b() {} // equals (hoisted): var a; console.log(a); // undefined a = function b() {}; console.log(a); // function b() {} |
在
在执行调用
JS不会以这种方式搜索代码中的函数。此外,
1 2 3 | function a() {console.log(arguments[0])} a(function b() {}); //function b() {} |
但是,这并不意味着您实际上可以在