【问题标题】:New to JS, trying to understand hoisting [duplicate]JS新手,试图理解提升[重复]
【发布时间】:2012-12-04 09:04:52
【问题描述】:

可能重复:
Redeclare JavaScript Variable

我有下一段代码:

var i = 11;
alert(i);
function a(){
    alert(i);
    var i = 2;
    alert(i);
}
a()

第二个alert(i)(在函数内部)产生undefined。我猜这与 JS 引擎在代码中运行的方式有关——也许它在遍历代码之前没有先存储变量?

反正我认为这不是问题是JS,因为它支持提升。我可能弄错了——有人愿意解释一下吗?

谢谢!

【问题讨论】:

标签: javascript undefined hoisting


【解决方案1】:

JavaScript 确实将 declarations 提升到它们发生的范围的顶部,但是分配发生在您期望它们发生的地方。您的代码被有效地解析如下:

/* Function declarations are hoisted first, which is why you can invoke a
   function before it appears to be defined in the source */
function a() {
    var i; // Declaration is hoisted (this i shadows the outer i)
    alert(i);
    i = 2; // Assignment to local i happens in place
    alert(i);
}
var i; // Declaration is hoisted (at this point, i === undefined)
i = 11; // Assignment happens in place
alert(i);
a();

这是详细的in the spec。进入新的执行上下文后,会发生以下情况:

对于 code 中的每个 VariableDeclarationVariableDeclarationNoIn d,按源文本顺序执行

  • dn成为d中的标识符
  • varAlreadyDeclared 成为调用 env 的 HasBinding 具体方法并传递 dn 作为参数的结果。
  • 如果 varAlreadyDeclaredfalse,那么
    • 调用 env 的 CreateMutableBinding 具体方法,传递 dnconfigurableBindings 作为参数。
    • 调用 env 的 SetMutableBinding 具体方法,传递 dnundefinedstrict 作为参数。

【讨论】:

  • 当解释器遇到之前没有关键字var的函数变量时,不会发生提升吗? OP 正在创建一个新变量i,它是函数范围的,对吧?
  • @limelights - 在进入任何执行上下文时发生提升。当控制进入a 函数时,解释器在开始执行代码之前查找任何声明并在新执行上下文的环境记录中为其标识符创建绑定。
  • 确实function a() 第一行上的var i; 具有该函数的本地范围,因此将是undefined 直到i = 2;
  • @JamesAllardice 啊,我明白了。那么,当控件提升一个变量时,它并不总是提升到全局上下文而是提升到本地上下文的顶部,除非关键字var 被忽略,这是错误的吗?
  • @limelights - 如果 var 关键字被遗漏,那么您没有声明。它根本不会被吊起。您只需分配给全局对象的属性。
猜你喜欢
  • 2016-01-21
  • 1970-01-01
  • 2022-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-13
  • 1970-01-01
  • 2016-10-04
相关资源
最近更新 更多