【问题标题】:Variable hoisting inside IIFE (lazy parsing)IIFE 中的变量提升(惰性解析)
【发布时间】:2017-08-02 00:14:04
【问题描述】:

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

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

谁能解释一下。

【问题讨论】:

  • 它叫做hoisting。谷歌一下。
  • @Kinduser:不,这不是提升。
  • 我知道吊装,你能解释一下行为吗
  • @T.J.Crowder 在没有var 关键字的函数内部声明变量使其成为全局变量,它被提升到脚本中。不是吗?
  • @T.J.Crowder 感谢您告诉我。撤回了我的投票

标签: javascript hoisting


【解决方案1】:

您所看到的与吊装无关。

您的第一个示例非常简单:

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

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

您的第二个示例省略了var

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

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

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

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

FunctionExpression : functionBindingIdentifier (FormalParameters) {FunctionBody}

  1. 如果 FunctionExpression 的函数代码是严格模式代码,则让 strict 为真。否则让 strict 为假。
  2. scope 为正在运行的执行上下文的 LexicalEnvironment。
  3. funcEnv 为 NewDeclarativeEnvironment(scope)。
  4. envRec成为funcEnv的EnvironmentRecord。
  5. nameBindingIdentifier 的 StringValue。
  6. 执行 envRec.CreateImmutableBinding(name, false)。
  7. ...

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

请注意,由函数声明创建的标识符(绑定)不是这样,它是可变的;但是函数表达式和函数声明对待由函数名创建的标识符完全不同。 (例如:函数声明将名称放在声明所在的范围内,但函数表达式没有。)

【讨论】:

  • 你知道为什么它是只读的,但是没有 IIFE 它将值覆盖为 123
  • @ankurkushwaha:在没有 IIFE 的 sn-p 中,您也使用 var
  • @ankurkushwaha:事实上,IIFE 在这里是无关紧要的。 var 的缺席或存在造成了不同。
  • 我同意@ankurkushwaha,为什么没有 iife 时它可以正常工作?即使使用 iife,它也适用于 var 关键字。为什么会这样?
猜你喜欢
  • 2017-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-22
  • 1970-01-01
  • 1970-01-01
  • 2013-07-12
  • 1970-01-01
相关资源
最近更新 更多