【问题标题】:Javascript Hoisting : difference between calling x and window.xJavascript 提升:调用 x 和 window.x 的区别
【发布时间】:2015-09-16 10:10:33
【问题描述】:

谁能解释以下场景中的吊装行为?

alert(x);
var x = 10;

Result: alert-undefined

在以下情况下,x 没有使用 'var' 关键字定义 - 因此附加到全局范围。

alert(x);
x = 10; // not given a var

Result: error

如果我们将 x 替换为 window.x,我们会得到未定义的警报!

alert(window.x); // calling the variable with window namespace
x = 10; // not given a var

Result: alert-undefined

你能解释一下为什么用变量名 (x) 和窗口命名空间 (window.x) 调用变量(附加到全局范围)不同吗?

【问题讨论】:

  • 您是否尝试过与window["x"]相同的程序?
  • @TomDoodler window["x"] 等于 window.x 所以它不会有任何区别。
  • 警报(x);变量 x = 10;等于 var x;警报(x); x=10;所以第一个是未定义的
  • 如果你想要一个连贯的行为,请使用"use strict"
  • 为了完整起见,this post 实际上描述了 JS 中更奇怪的行为

标签: javascript hoisting


【解决方案1】:

“提升”一词经常被误解为将某些语句移到其执行上下文的顶部,这不是发生的情况,也是应避免使用该术语的原因。

实际发生的情况是首先处理所有声明,因此使用 var 声明的任何变量(以及由函数声明创建的任何函数)在执行任何代码之前都存在。然后代码执行开始。

所以变量 x 在执行任何代码之前被创建并赋值为 undefined(根据 ECMA-262),然后在执行期间,它可能会被赋值一些价值。

所以在这种情况下:

alert(x);
var x = 10;

x 在调用 alert 时存在,但尚未被分配除 undefined 以外的值。

在:

alert(x);
x = 10;

x 未声明,因此在调用 alert 时它不存在,因此出现错误。在警报之后(如果代码继续运行),对 x 的赋值将创建名为 x 的全局(浏览器中的窗口)对象的属性并为其赋值10 个。

在:

alert(window.x);
x = 10;

ECMAScript 的一个怪癖是全局变量也可用作全局对象的属性。表达式window.x 尝试读取窗口对象的x 属性。由于不存在这样的属性,因此返回 undefined。然后下一条语句将 x 创建为全局变量,因此 window.x 现在存在,值为 10。

【讨论】:

  • 感谢@RobG,所以它不仅仅是关于window.x,它对任何未声明的变量window.a、window.b ...等都有效:D
  • 是的。 window.x 正在解析对象上的属性名称,它具有不同的规则来解析执行上下文和范围链中的标识符。在第一种情况下,如果属性不存在,您会得到 undefined。在第二个中,抛出一个错误。为什么?因为这就是规范所说的应该发生的事情。 ;-)
【解决方案2】:

var x 在其有效的整个范围内提升变量,因此 名称 x 在范围内的任何位置都可用且有效。它的初始值为undefined,只有在alert之后才会收到它的值。

如果是普通的x,变量不会被提升,因为没有var,所以冒泡到window 并且它在那里的创建只发生在x = 10 行上,这是在警报之后,这意味着该变量在您尝试提醒它时完全未定义且无效。

任何对象的任何不存在的属性都会返回undefined,因此在未设置该属性时测试window.x 会按预期返回undefined。这就是您在 Javascript 中进行成员资格测试的方式:检查特定属性是否等于 undefined

【讨论】:

    【解决方案3】:

    在第一种情况下,var x 被提升,因此当您调用它时x 确实存在(即使该值未定义)

    在第二种情况下,当你说y = 10时,你实际上是在说window.y = 10,所以根本没有提升,这就是为什么它根本找不到变量并给你一个错误。

    【讨论】:

      【解决方案4】:
      alert(x);
      var x = 10;
      

      将被视为

      var x;
      alert(x);
      x = 10;
      

      所以在alertx 的时候,undefined 的值是default

      alert(x);
      x = 10;
      

      将被视为

      alert(x);
      x = 10; // If this line runs in use strict mode then this line will throw error otherwise in non strict mode x will be added to global object ie. window
      

      throw error 也是如此,因为 xalert 时是 undefined

      alert(window.x); 
      x = 10;
      

      将被视为

      alert(window.x);
      x = 10;
      

      alert 将提醒undefined,因为windowobject,并且在alert 时它没有名为x 的属性,所以undefined 稍后,x = 10; 行将在 non strict mode 中添加 xglobal object,在 strict mode 中添加 throw error

      【讨论】:

        猜你喜欢
        • 2019-09-11
        • 1970-01-01
        • 2017-09-03
        • 1970-01-01
        • 2020-07-21
        • 1970-01-01
        • 2020-09-09
        • 1970-01-01
        • 2018-07-28
        相关资源
        最近更新 更多