JavaScript 全局 this

深入解析 JavaScript 全局对象的演进:从 window、self、frames 到 globalThis,以及不同环境下全局对象的差异和访问方式。

为什么理解全局 this 是理解 JavaScript 环境的基础

JavaScript 在不同的运行环境中执行:浏览器、Node.js、Web Worker、Deno 等。每个环境都有自己的"全局对象",提供语言核心功能和宿主 API。

理解全局对象的演进历史和 globalThis 的统一方案,是理解 JavaScript 多端运行能力的基础。


一、全局对象的历史

1.1 浏览器中的 window

在浏览器中,全局对象是 window

// 浏览器环境
console.log(window === this); // true
console.log(window === globalThis); // true

// 在全局作用域声明的变量成为 window 的属性
var globalVar = 'hello';
console.log(window.globalVar); // 'hello'

// let/const 不挂载到 window
let localVar = 'world';
console.log(window.localVar); // undefined

1.2 Node.js 中的 global

Node.js 使用 global 作为全局对象:

// Node.js 环境
console.log(global === globalThis); // true

// 全局变量不是 global 的属性(除非显式赋值)
global.myVar = 'test';
console.log(global.myVar); // 'test'

1.3 Web Worker 中的 self

Web Worker 中没有 window,使用 self

// Web Worker 环境
console.log(self === globalThis); // true
console.log(self.toString()); // '[object DedicatedWorkerGlobalScope]'

二、globalThis 的统一方案

2.1 问题

不同环境使用不同的全局对象名称:

// 传统做法:环境检测
const getGlobal = () => {
  if (typeof window !== 'undefined') return window;
  if (typeof global !== 'undefined') return global;
  if (typeof self !== 'undefined') return self;
  throw new Error('Cannot find global object');
};

// 非常繁琐且容易出错

2.2 ES2020 的解决方案

ES2020 引入了 globalThis,提供统一访问全局对象的方式:

// 所有环境都支持
console.log(globalThis.Array === Array); // true
console.log(globalThis.Object === Object); // true
console.log(globalThis.JSON === JSON); // true

2.3 globalThis 的 polyfill

ES2020 之前的浏览器需要 polyfill:

(function() {
  if (typeof globalThis === 'undefined') {
    Object.defineProperty(Object.prototype, '__magic__', {
      get: function() {
        return this;
      },
      configurable: true
    });
    __magic__.globalThis = __magic__;
    delete Object.prototype.__magic__;
  }
})();

三、全局对象的特性

3.1 全局对象的属性

全局对象上有很多重要的属性和方法:

// 核心对象(标准库)
globalThis.Object;
globalThis.Array;
globalThis.Function;
globalThis.String;
globalThis.Number;
globalThis.Boolean;
globalThis.Symbol;
globalThis.Error;
globalThis.JSON;
globalThis.Math;
globalThis.Date;

// 核心函数
globalThis.parseInt;
globalThis.parseFloat;
globalThis.isNaN;
globalThis.isFinite;
globalThis.eval;
globalThis.encodeURI;
globalThis.decodeURI;

// 构造函数
globalThis.RegExp;
globalThis.Map;
globalThis.Set;
globalThis.WeakMap;
globalThis.WeakSet;
globalThis.Promise;
globalThis.Proxy;

3.2 宿主环境添加的属性

// 浏览器环境
globalThis.alert;
globalThis.fetch;
globalThis.console;
globalThis.document;
globalThis.navigator;
globalThis.location;

// Node.js 环境
globalThis.process;
globalThis.require;
globalThis.module;
globalThis.exports;
globalThis.__dirname;
globalThis.__filename;

四、全局对象的访问模式

4.1 在任何地方访问全局对象

// 推荐方式
const g = typeof globalThis !== 'undefined' 
  ? globalThis 
  : typeof window !== 'undefined' 
    ? window 
    : typeof global !== 'undefined' 
      ? global 
      : typeof self !== 'undefined' 
        ? self 
        : {};

// 或者使用 Function
const getGlobal = (new Function('return this'))();

4.2 模块中访问全局对象

// ES Module 中
import url from 'url';

// CommonJS 中
const url = require('url');

// 动态代码中
const globals = new Function('return this')();

五、面试高频考点

考点 1:不同环境的全局对象

  • 浏览器:window
  • Node.js:global
  • Web Worker:self
  • ES2020+:globalThis

考点 2:var 声明与全局对象

用 var 在全局作用域声明的变量会成为全局对象(window/global)的属性,而 let/const 不会。

考点 3:globalThis 的意义

统一不同 JavaScript 运行环境的全局对象访问方式,解决了历史遗留的兼容性问题。


延展阅读