Javascript 提升:调用 x 和 window.x 的区别

Javascript Hoisting : difference between calling x and window.x

任何人都可以解释以下场景中的提升行为吗?

alert(x);
var x = 10;

Result: alert-undefined

在下面的例子中,x 不是使用 'var' 关键字定义的 - 因此附加到全局范围。

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

Result: error

如果我们用 window.x 替换 x,我们会收到未定义的警报!

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

Result: alert-undefined

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

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

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

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

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

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

术语 "hoisting" 经常被误解为某些语句被移动到其执行上下文的顶部,这不是实际发生的情况,也是应避免使用该术语的原因。

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

因此在执行任何代码之前创建变量 x 并分配值 undefined (根据 ECMA-262),然后稍后,在执行过程中,可能会被赋值。

所以在这种情况下:

alert(x);
var x = 10;

x 在调用 alert 时存在,但尚未分配 undefined[= 以外的值46=].

在:

alert(x);
x = 10;

x 没有声明,所以当调用 alert 时它不存在,因此错误。在警报之后(如果代码保持 运行),对 x 的赋值将创建全局的 属性(在浏览器中为 window)名为 x 的对象并为其赋值 10.

在:

alert(window.x);
x = 10;

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

alert(x);
var x = 10;

将被视为

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

所以在 alertx 的值是 undefined by 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,因为 window 是一个 object,并且在 [=16] 时没有 属性 命名为 x =] 所以 undefined 如果在 non strict mode 中,行 x = 10; 会将 x 添加到 global object,如果在 strict mode

中,则会添加 throw error