全局变量/全局命名空间上的 JavaScript 策略



今天我遇到了一个问题,top是一个预先存在的全局变量。

const left = 1;
const right = 2;
const top = 3;
const bottom = 4;
console.log(left, right, top, bottom);

结果:

Uncaught SyntaxError: Identifier 'top' has already been declared

我想直到今天我都很幸运,大多数时候我对名为top的变量的使用都在函数中。

我需要担心浏览器添加新的全局变量会在未来破坏代码?似乎在 es6 导入之前,几乎所有浏览器库都使用全局变量,除非它们有构建步骤。但是,查看top示例,浏览器似乎可以随时添加新的不可设置的全局变量,因此应不惜一切代价避免它们。我看到一些变量,例如HTMLElement是可分配的。

console.log(HTMLElement);
HTMLElement = 'foo';
console.log(HTMLElement);

结果:

function HTMLElement() { [native code] }
foo

top是一些遗留的东西,但浏览器规格承诺将来不会做更多的事情吗?就像我无法分配window

const window = 'foo';
console.log(window);

结果:

SyntaxError: Identifier 'window' has already been declared

但我可以在节点中分配process

Welcome to Node.js v12.6.0.
Type ".help" for more information.
> process
process {
version: 'v12.6.0',
versions: {
node: '12.6.0',
...
}
> process = 'foo'
'foo'
> process
'foo'
> 

我需要担心浏览器添加新的全局变量会破坏代码吗?

你不应该担心它。JS和HTML的新功能经过了广泛的测试。浏览器通常会部署代码来监视与计划的 API 的不兼容性,以确定它们是否可以安全交付。(例如,如果浏览器想要添加globalThis.foo,它可能会部署一个计数器,该计数器在每次代码访问或分配给globalThis.foo时递增,以了解它是否已用于其他用途(。此外,浏览器的开发人员预览版允许开发人员在问题走得太远之前发现它们。您可能会发现这很有趣:https://developers.google.com/web/updates/2018/03/smooshgate。

话虽如此,我仍然不建议你去创建很多全局变量,这不是最奇妙的模式。

顶部是一些遗留的东西,但浏览器规格承诺将来不会做更多的事情吗?就像我无法分配窗口一样

这确实是遗产,尽管我不知道有任何这样的承诺。HTML 标准对window.top的定义如下(从 https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-window-object 年开始(:

[LegacyUnforgeable] readonly attribute WindowProxy? top;

[LegacyUnforgeable]表示在window上创建属性top,属性属性configurable设置为false。隐藏不可配置属性的全局声明将失败,因为它们无法更改值。

但我可以在节点中分配进程

这是因为 Node.js 中的process是可配置的属性。

> Object.getOwnPropertyDescriptor(globalThis, 'process')
{
get: [Function: get],
set: [Function: set],
enumerable: false,
configurable: true
}

最后要注意的是,赋值和声明之间存在差异。您仍然可以分配给不可配置的属性,只要它们是可写的或提供资源库。

最新更新