感謝阮一峰老師的ECMAScript6入門這本書,大家可以來這里學習並支持老師的書。
ES5 的頂層對象,本身也是一個問題,因為它在各種實現里面是不統一的。
- 瀏覽器里面,頂層對象是
window,但 Node 和 Web Worker 沒有window。 - 瀏覽器和 Web Worker 里面,
self也指向頂層對象,但是 Node 沒有self。 - Node 里面,頂層對象是
global,但其他環境都不支持。
同一段代碼為了能夠在各種環境,都能取到頂層對象,現在一般是使用this變量,但是有局限性。
- 全局環境中,
this會返回頂層對象。但是,Node 模塊和 ES6 模塊中,this返回的是當前模塊。 - 函數里面的
this,如果函數不是作為對象的方法運行,而是單純作為函數運行,this會指向頂層對象。但是,嚴格模式下,這時this會返回undefined。 - 不管是嚴格模式,還是普通模式,
new Function('return this')(),總是會返回全局對象。但是,如果瀏覽器用了CSP(Content Security Policy,內容安全政策),那么eval、new Function這些方法都可能無法使用。
綜上所述,很難找到一種方法,可以在所有情況下,都取到頂層對象。下面是兩種勉強可以使用的方法。
// 方法一
(typeof window !== 'undefined'
? window
: (typeof process === 'object' &&
typeof require === 'function' &&
typeof global === 'object')
? global
: this);
// 方法二
var getGlobal = function () {
if (typeof self !== 'undefined') { return self; }
if (typeof window !== 'undefined') { return window; }
if (typeof global !== 'undefined') { return global; }
throw new Error('unable to locate global object');
};
現在有一個提案,在語言標准的層面,引入global作為頂層對象。也就是說,在所有環境下,global都是存在的,都可以從它拿到頂層對象。
墊片庫system.global模擬了這個提案,可以在所有環境拿到global。
// CommonJS 的寫法
require('system.global/shim')();
// ES6 模塊的寫法
import shim from 'system.global/shim'; shim();
上面代碼可以保證各種環境里面,global對象都是存在的。
// CommonJS 的寫法
var global = require('system.global')();
// ES6 模塊的寫法
import getGlobal from 'system.global';
const global = getGlobal();
上面代碼將頂層對象放入變量global。
