你知道JS全局变量是如何工做的吗?

原文: 2ality.com/2019/07/glo…javascript

翻译: 刘小夕html

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

更多文章可戳: github.com/YvetteLau/B…git

1.做用域

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

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

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

在示例中,funcif 的外层做用域。数据结构

2.词法做用域

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

  • 将变量名映射到变量值的环境记录(能够想象成是字典)。这是 JavaScript 存储变量的地方。环境记录中的一个 key-value 条目称为绑定。
  • 对外部环境的引用 - 表示当前环境所表明的做用域的外部做用域的环境。

所以,嵌套做用域树能够由嵌套环境树表示。this

3.全局对象

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

  • 无处不在:全局 this
  • 全局对象的其余名称取决于平台和语言构造:
    • window:是引用全局对象的经典方式,但它只适用于普通浏览器环境; 不在 Node.jsWeb Workers 中。
    • self:在浏览器中随处可用,包括 Web Workers。 可是 Node.js 不支持它。
    • global:仅在 Node.js 中可用。

全局对象包含全部内置全局变量。

4.全局环境

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

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

  • 对象式环境记录,其做用相似于普通环境记录,但保持其绑定与对象同步。 在这种状况下,对象是全局对象。
  • 声明式环境记录。

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

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

4.1建立变量

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

  • 顶级 constletclass 在声明式环境记录中建立绑定。
  • 顶级 var 和函数声明在对象式环境记录中建立绑定。
<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既有全局变量又有全局对象?

一般认为全局对象是错误的。所以,较新的构造(如 constletclasses)会建立正常的全局变量,不会成为全局对象的属性。(在script做用域内时)。

值得庆幸的是,大多数用现代 JavaScript 编写的代码都存在于 ECMAScript 模块和CommonJS 模块中。每一个模块都有本身的做用域,这就是为何管理全局变量的规则不多对基于模块的代码很重要。

最后谢谢各位小伙伴愿意花费宝贵的时间阅读本文,若是本文给了您一点帮助或者是启发,请不要吝啬你的赞和Star,您的确定是我前进的最大动力。github.com/YvetteLau/B…

关注公众号,加入技术交流群

相关文章
相关标签/搜索