全局对象与可变对象

时间:2020-05-01 09:40:37

标签: javascript

因此,我了解了提升,作用域链和执行上下文。但是,我无法掌握一件事。 变量对象和全局对象是否不同? 并且,“执行上下文对象”与全局对象相同吗?

这是我尝试获得答案的一些代码。

let variable = 0;

function updateVar(value) {
  this.variable = value;  
}

updateVar(1);

console.log(variable);
// 0

/* 
If I remove the 'this' keyword in the updateVar() function, 
the console logs 1.
Why?   

谢谢您的帮助! 朱利安

1 个答案:

答案 0 :(得分:4)

听起来您可能正在阅读一些过时的材料。自1999年第三版以来,该规范中就没有使用“变量对象”一词。:-)从ES5开始使用的术语是environment record

[环境记录]和全局对象是否不同?

是的。但是全局环境是一对嵌套的环境:外部环境使用global object作为其绑定对象(这在ES3中大致是“变量对象”的意思)。然后是letconstclass全局变量的内部变量,它们不会成为全局对象的属性。您可以看到,如果您在规范中以SetRealmGlobalObject开始,然后按照其执行的NewGlobalEnvironment进行操作,这会使用全局对象进行绑定来创建new object environment record

而且,“执行上下文对象”与全局对象相同吗?

execution context 具有环境记录。

如果我在updateVar()函数中删除了'this'关键字,
控制台日志1.
为什么?

由于两个嵌套的全局环境:

+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
|         environment record for global object bindings         |
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
|   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+    |
|   |  environment record for global declarative bindings  |    |
|   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+    |
|   |                                                      |    |
|   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+    |
|                                                               |
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+

因此,当您在全局范围内执行此操作时:

let variable = 0;

它在此内部全局环境记录中创建绑定:

+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
|         environment record for global object bindings         |
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
|   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+    |
|   |  environment record for global declarative bindings  |    |
|   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+    |
|   | variable: 0                                          |    |
|   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+    |
|                                                               |
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+

执行此操作时:

function updateVar(value) {
  this.variable = value;  
}
updateVar(1);

在调用updateVar期间,this引用了全局对象。因此this.variable = 1在该对象上创建一个属性(由于该对象是最外面的绑定对象,因此是全局的):

+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
|         environment record for global object bindings         |
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
| variable: 1                                                   |
|                                                               |
|   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+    |
|   |  environment record for global declarative bindings  |    |
|   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+    |
|   | variable: 0                                          |    |
|   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+    |
|                                                               |
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+

在全局范围内执行console.log(variable)时,variable解析为声明性环境绑定,并获得值0

如果您改为这样做:

执行此操作时:

function updateVar(value) {
  variable = value;   // <=== No `this`
}
updateVar(1);

variable解析为声明性环境绑定,而不是在全局对象上创建属性,因此您正在更新该绑定:

+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
|         environment record for global object bindings         |
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
|   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+    |
|   |  environment record for global declarative bindings  |    |
|   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+    |
|   | variable: 1                                          |    |
|   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+    |
|                                                               |
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+

使用this中的updateVar,您可以看到它通过使用window上的变量在全局对象上创建属性(该变量是浏览器中全局对象的代理) :

let variable = 0;
function updateVar(value) {
  this.variable = value;  
}
updateVar(1);

console.log(variable);
console.log(window.variable);

相关问题