IIFE 中的变量提升(惰性解析)

Variable hoisting inside IIFE (lazy parsing)

我在以下情况下得到非常奇怪的输出:

function test(){
   var test=123;
   console.log(test)
}
// this output : 123

(function test(){
   var test=123;
   console.log(test)
})()

// this output: 123 

但是当使用下面的代码时

(function test(){
   test=123;
   console.log(test)
})()

//output:

function test(){
    test=123;
    console.log(test)
}

谁能解释一下。

您看到的内容与提升无关。

你的第一个例子很简单:

(function test(){
   var test=123;
   console.log(test)
})()

您正在函数范围内创建一个名为 test 的变量(通过 var),并为其赋值,然后输出该值。

你的第二个例子遗漏了 var:

(function test() {
    test = 123;
    console.log(test);
})();

...所以 test 具有完全不同的含义:在由命名函数表达式创建的函数中,函数的名称是解析为函数的标识符。因此,该代码中的 test 是函数的标识符。

当您使用函数表达式时,该标识符是 只读,因此您的 test = 123; 行将被忽略,并且 console.log 行输出函数的表示(好像 test = 123; 根本不存在)。

我忘记了标识符是只读的(当由 表达式 创建时),但它是:来自 the specification:

FunctionExpression : functionBindingIdentifier ( FormalParameters ) {FunctionBody}

  1. If the function code for FunctionExpression is strict mode code, let strict be true. Otherwise let strict be false.
  2. Let scope be the running execution context's LexicalEnvironment.
  3. Let funcEnv be NewDeclarativeEnvironment(scope).
  4. Let envRec be funcEnv's EnvironmentRecord.
  5. Let name be StringValue of BindingIdentifier.
  6. Perform envRec.CreateImmutableBinding(name, false).
  7. ...

注意第 6 步:创建标识符的绑定是 不可变的(无法更改)。

请注意,对于可变的函数 声明 创建的标识符(绑定)而言,情况并非如此;但是 function expressions 和 function declarations 对待由函数名创建的标识符完全不同。 (例如:函数声明将名称放在声明所在的范围内,但函数表达式不会。)