IIFE内可变吊装(延迟解析)

时间:2017-03-11 18:21:04

标签: javascript hoisting

我在下面的场景中得到了一个非常奇怪的输出:

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)
}

任何人都可以解释一下。

1 个答案:

答案 0 :(得分:9)

您所看到的与吊装无关。

你的第一个例子很简单:

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

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

你的第二个例子没有var

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

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

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

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

  

FunctionExpression:functionBindingIdentifier(FormalParameters){FunctionBody}

     
      
  1. 如果 FunctionExpression 的功能代码是严格模式代码,请将 strict 设为true。否则,请将 strict 设为false。
  2.   
  3. 范围成为正在运行的执行上下文的LexicalEnvironment。
  4.   
  5. funcEnv 成为NewDeclarativeEnvironment(范围)。
  6.   
  7. envRec 成为 funcEnv 的EnvironmentRecord。
  8.   
  9. name BindingIdentifier 的StringValue。
  10.   
  11. 执行envRec.CreateImmutableBinding( name ,false)。
  12.   
  13. ...
  14.   

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

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