因此,我了解了提升,作用域链和执行上下文。但是,我无法掌握一件事。 变量对象和全局对象是否不同? 并且,“执行上下文对象”与全局对象相同吗?
这是我尝试获得答案的一些代码。
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?
谢谢您的帮助! 朱利安
答案 0 :(得分:4)
听起来您可能正在阅读一些过时的材料。自1999年第三版以来,该规范中就没有使用“变量对象”一词。:-)从ES5开始使用的术语是environment record。
[环境记录]和全局对象是否不同?
是的。但是全局环境是一对嵌套的环境:外部环境使用global object作为其绑定对象(这在ES3中大致是“变量对象”的意思)。然后是let
,const
和class
全局变量的内部变量,它们不会成为全局对象的属性。您可以看到,如果您在规范中以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);