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

v7pvogib  于 2023-04-10  发布在  Java
关注(0)|答案(1)|浏览(118)

今天我遇到了一个问题,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 import几乎所有的浏览器库都使用全局变量,除非它们有构建步骤。但是,看看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'
>
ddrv8njm

ddrv8njm1#

我需要担心浏览器添加新的全局变量会在将来破坏代码吗?
你不必担心。JS和HTML的新功能都经过了广泛的测试。浏览器通常会部署代码,监视与计划中的API的不兼容性,以确定它们是否可以安全发布。(例如,如果浏览器想要添加globalThis.foo,它可能会部署一个计数器,每当代码访问或分配给globalThis.foo时,该计数器就递增,以了解它是否已经被用于其他事情)。此外,浏览器的开发人员预览版允许开发人员在他们做得太远之前抓住可能的问题。你可能会发现这很有趣:https://developers.google.com/web/updates/2018/03/smooshgate
话虽如此,我仍然不建议你去创建大量的全局变量,这不是最奇妙的模式。
top是一些遗留的东西,但浏览器规格承诺在未来不会做更多的事情吗?就像我不能分配窗口
它确实是遗留的,尽管我不知道有任何这样的承诺。HTML标准定义window.top如下(来自https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-window-object):

[LegacyUnforgeable] readonly attribute WindowProxy? top;

[LegacyUnforgeable]意味着属性top是在window上创建的,属性属性configurable设置为false。隐藏不可配置属性的全局声明将失败,因为它们无法更改值。
但我可以在节点中分配进程
这是因为Node.js中的process是一个可配置的属性。

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

最后一点,赋值和声明是有区别的。你仍然可以赋值给不可配置的属性,只要它们是可写的或者提供了一个setter。

相关问题