<返回更多

JS全局变量是如何工作的?

2019-10-09    
加入收藏
原文: https://2ality.com/2019/07/global-scope.html翻译: 刘小夕

在这篇博文中,我们将研究 JAVAScript 的全局变量是如何工作的。如: scripts的范围,所谓的全局对象等等。

1.作用域

变量的词法作用域(简称:作用域)是可以访问它的程序的区域。 JavaScript 的作用域是静态的(它们在运行时不会改变)并且它们可以嵌套 - 例如:

function
 func
()
 
{
 
// (A)
 
const
 foo 
=
 
1
;
 
if
 
(
true
)
 
{
 
// (B)
 
const
 bar 
=
 
2
;
 
}
}

if 语句引入的作用域(行B)嵌套在函数 func()(行A)的作用域内。

在示例中, func 是 if 的外层作用域。

2.词法作用域

在 JavaScript 语言规范中,作用域是通过词法作用域“实现”的。它们由两部分组成:

因此,嵌套作用域树可以由嵌套环境树表示。

3.全局对象

全局对象是一个对象,其属性是全局变量。

全局对象包含所有内置全局变量。

4.全局环境

全局作用域是“最外层”作用域 - 它没有外部作用域。它的环境是全局环境。每个环境都通过由外部引用链接的一系列环境与全局环境相关联。全局环境的外部引用为 null。

全局环境结合了两个环境记录

下图显示了这些数据结构。

 

JS全局变量是如何工作的?

 

 

接下来的两个小节将解释如何组合对象记录和声明式记录。

4.1创建变量

为了创建一个真正全局的变量,你必须处于全局作用域内 - 必须要在 scripts 的顶层:

<
script
>
 
const
 one 
=
 
1
;
 
var
 two 
=
 
2
;
</
script
>
<
script
>
 
// All scripts share the same top-level scope:
 console
.
log
(
one
);
 
// 1
 console
.
log
(
two
);
 
// 2
 
// Not all declarations create properties of the global object:
 console
.
log
(
window
.
one
);
 
// undefined
 console
.
log
(
window
.
two
);
 
// 2
</
script
>

此外,全局对象包含所有内置全局变量,并通过对象式记录将它们给全局环境。

4.2读取/设置变量

当我们获取或设置变量并且两个环境记录都具有该变量的绑定时,声明式环境记录将获胜:

<
script
>
 let foo 
=
 
1
;
 
// 声明式环境记录
 globalThis
.
foo 
=
 
2
;
 
// 对象式环境记录
 console
.
log
(
foo
);
 
// 1 (声明式记录获胜)
 console
.
log
(
globalThis
.
foo
);
 
// 2
</
script
>

5.模块环境

每个模块都有自己的环境,它存储所有顶级声明 - 包括导入。模块环境的外部环境是全局环境。

结论:为什么JavaScript既有全局变量又有全局对象?

通常认为将全局变量挂载到全局对象上是错误的。因此,较新的构造(如 const, let 和 classes)会创建正常的全局变量,不会成为全局对象的属性。(在 script作用域内时)。

值得庆幸的是,大多数用现代 JavaScript 编写的代码都存在于 ECMAScript 模块和 CommonJS模块中,每个模块都有自己的作用域。

声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>