var 与 let for *globals*...为什么我应该关心“全局对象上的属性”?

问题描述 投票:0回答:1

我见过这个(或类似的):

在顶层,与 var 不同,let 不会在 全局对象。

很多次。

我的问题是:我为什么要关心?

或者,换句话说:这是一个没有区别的区别吗?

或者,这里是否有一些深奥的魔法需要理解?

无论如何,我找到了这个定义(https://developer.mozilla.org/en-US/docs/Glossary/Global_variable):

全局变量

全局变量是在全局范围内声明的变量 换句话说,一个在所有其他范围内都可见的变量。

在 JavaScript 中,它是全局对象的属性。

我认为最后一句话已经过时了? 或者“让”全局在某种程度上是二等全局?

javascript global-variables global
1个回答
0
投票

首先,请记住,不仅仅是您的代码位于全局范围内。在 ES6 模块出现之前,最好的做法是尽最大努力将代码与全局范围隔离。因此,手工包装的模块可能如下所示:

/* some library code wrapped as a module */
(function someThirdPartyLibrary() {
  var myGlobal = "hello";
  
  setTimeout(
    () => console.log(myGlobal.toUpperCase()), 
    1000
  );
})();

/* /library code */

/* other code */

var myGlobal = 42;

console.log(myGlobal);

这适用于隔离。有两个不同的变量,称为

myGlobal
,并且都有不同的值。

然而,使用模块进行包装的做法是在多次代码未能正确执行之后出现的。这导致很难发现和诊断错误。考虑相同但没有隔离:

/* some library code NOT wrapped as a module */ var myGlobal = "hello"; setTimeout( () => console.log(myGlobal.toUpperCase()), 1000 ); /* /library code */ /* other code */ var myGlobal = 42; console.log(myGlobal);

现在有一个问题。

引入新的

window

级别变量时,情况会进一步复杂化。旧代码可能会停止工作。出于基本相同的根本原因——争夺相同的全局标识符。让我们说它不是一个库,而只是介绍

myGlobal
:
 的浏览器

/* imagine a browser update adds a new thing */ Object.defineProperty(window, "myGlobal", { value: "hello", writable: false }) /* /browser update */ /* other existing code */ var myGlobal = 42; console.log(myGlobal); //"hello"

这在过去是一个更大的问题。臭名昭著的是

name

使用变量“name”不适用于 JS 对象
许多

window

级属性现在作为变量发挥得更好。但是,仍然不建议在全局对象上使用属性。这就是为什么

const
let
创建全局
标识符
,但与 var 不同,全局对象上没有
属性。这允许代码能够工作
,因为全局属性和具有相同名称但用
let/const
 声明的全局变量是不同的东西:

/* imagine a browser update adds a new thing */ Object.defineProperty(window, "myGlobal", { value: "hello", writable: false }) /* /browser update */ /* other existing code */ let myGlobal = 42; //<-- now a let console.log(myGlobal); //42
如果需要,仍然可以通过

全局对象显式访问全局对象上的属性。:

/* imagine a browser update adds a new thing */ Object.defineProperty(window, "myGlobal", { value: "hello", writable: false }) /* /browser update */ /* other code */ let myGlobal = 42; //<-- now a let console.log(myGlobal); //42 console.log(window.myGlobal); //"hello"


let

/

const

还有其他防止错误的保护措施,例如重新声明时的早期错误。但全局变量和全局属性的分离是包的一部分。所有这些都建立在过去的教训之上,过去由于某种原因而发生的全局冲突会导致错误。通常很难诊断,很多时候也完全令人惊讶。不依赖全局对象的属性使代码在发生更改时具有更大的弹性。充当隐式隔离,类似于模块提供的功能。

    

© www.soinside.com 2019 - 2024. All rights reserved.