[翻译]ES 提案: global

时间:2021-11-21 14:40:29

Jordan Harband 的 ECMAScript 提案“global”现在处于第三阶段。该提案提供了一种新的用于访问全局对象的标准方式。

全局对象的引用

下面是常用的几种引用全局对象的方式:

  • 全局变量:
    • 全局变量 window: 这是经典的全局对象。但是在 Node.js 和 Web Worker 里不可用。
    • 全局变量 self: 在 Web Worker 和一般浏览器中可用。但是 Node.js 不支持。有一些人使用 self 来使得代码能在 Web Workers 和一般浏览器的环境中都能生效。
    • 全局变量 global: 至今仅仅只有 Node.js 使用!
  • this:
    • 全局作用域里的 this : 指向全局对象。唯一的问题是 Node.js 模块和 ES6 模块有它们自己的作用域,而这意味着这里的 this 不会指向全局对象。
    • 非严格模式下函数调用里的 this: 如果你在非严格模式下调用一个函数(不是方法调用),函数的 this 会指向全局对象。在严格模式下,this 是 undefined。
    • new Function('return this')(): 在严格模式和非严格模式下同样有效,因为 new Function() 的参数总是在非严格模式下执行。下面是一个严重的警告:当你使用CSP (Content Security Policy)的时候, evalnew Function() 等等是不可用的。这使得这种返回 this 的方法在许多情况下不适宜使用。

提案

该 ECMAScript 提案提议:将全局变量 global 作为访问全局对象的标准方式。该提案也提议: Object.prototype  必须在全局对象的原型链里。下面的代码在现在的浏览器上是 true:

    > Object.prototype.isPrototypeOf(window)
true

最佳实践

现在,由于向后兼容的缘故,全局对象被认为是一个 JavaScript 不能摆脱错误。它影响性能,且通常是令人困惑的。

ECMAScript 6 提供了下面不会在全局作用域里创建全局属性(var 声明和函数声明会)的三种新的声明变量的方式来避免:

  • let 声明
  • const 声明
  • Class 声明

换句话说:全局对象的所有属性是全局变量,但不是所有的全局变量都是全局对象的属性。比如(在全局作用域执行):

    > var foo;
> 'foo' in window
true > let bar;
> 'bar' in window
false

通常情况下将全局变量只作为变量好于将其作为全局对象的属性,比如 window。这样就能在所有 JavaScript 平台上都有效。

另外,从 ES6 开始(甚至在这之前),多数 JavaScript 代码都存在模块里且永远都不会出现在全局作用域里。

因此,global 将大多时候与 polyfills 相关(global will mostly be relevant for polyfills)。

A polyfill

本提案的作者 Jordan Harband 为此写了一个polyfill

CommonJS 语法:

    var global = require('system.global')();

ES6 模块语法:

    import getGlobal from 'system.global';
const global = getGlobal();

这个包使用的是“最原生的”可用的访问方法(比如 Node.js 的 global,一般浏览器环境的 window 等等)。

获得全局对象的引用

在代码内部,这个 polyfill 使用 getPolyfill() 函数来计算得全局对象的引用。以下是实现方式:

    // polyfill.js
var implementation = require('./implementation');
module.exports = function getPolyfill() {
if (typeof global !== 'object' || !global || global.Math !== Math
|| global.Array !== Array) {
return implementation;
}
return global;
}; // implementation.js
if (typeof self !== 'undefined') {
module.exports = self;
} else if (typeof window !== 'undefined') {
module.exports = window;
} else if (typeof global !== 'undefined') {
module.exports = global;
} else {
module.exports = Function('return this')();
}

关于全局对象的更多信息

原文:ES proposal: global