globalThis

globalThis

globalThis 전역 속성은 전역 this 값을 담고 있으며, 이는 보통 전역 객체와 유사하다.

출처: globalThis - JavaScript | MDN

본문

Try it

function canMakeHTTPRequest() {
  return typeof globalThis.XMLHttpRequest === "function";
}

console.log(canMakeHTTPRequest());
// Expected output (in a browser): true

값(Value)

전역 this 객체.

globalThis의 속성 속성(Property attributes):

  • Writable: yes
  • Enumerable: no
  • Configurable: yes

참고: globalThis 속성은 configurable이고 writable하므로, 코드 작성자가 신뢰할 수 없는 코드를 실행할 때 이를 숨겨 전역 객체가 노출되는 것을 방지할 수 있다.

개요

역사적으로 전역 객체에 접근하려면 JavaScript 환경마다 다른 문법이 필요했다. 웹에서는 window, self, frames를 사용할 수 있지만, Web Workers에서는 self만 동작한다. Node.js에서는 이 중 어느 것도 동작하지 않으며 대신 global을 사용해야 한다. this 키워드는 non-strict 모드에서 실행되는 함수 내부에서 사용될 수 있지만, this는 모듈과 strict 모드 함수 내부에서는 undefined가 된다. 또한 Function('return this')()를 사용할 수도 있지만, 브라우저의 CSP 같은 eval()을 비활성화하는 환경에서는 이런 방식의 Function 사용을 막는다.

globalThis 속성은 환경을 가로질러 전역 this 값(따라서 전역 객체 자체)에 접근하는 표준적인 방법을 제공한다. windowself 같은 유사 속성과 달리, window와 non-window 컨텍스트 모두에서 동작한다는 것이 보장된다. 이렇게 하면 코드가 어떤 환경에서 실행되는지 알 필요 없이 일관된 방식으로 전역 객체에 접근할 수 있다. 이름을 기억하는 데 도움이 되도록, 전역 스코프에서 this 값이 globalThis라는 점을 기억하면 된다.

참고: globalThis는 일반적으로 전역 객체와 같은 개념이다(즉 globalThis에 속성을 추가하면 전역 변수가 된다). 이는 브라우저와 Node의 경우다. 다만 호스트는 전역 객체와 무관한 다른 값을 globalThis에 제공할 수도 있다.

HTML과 WindowProxy

많은 엔진에서 globalThis는 실제 전역 객체에 대한 참조가 되지만, 웹 브라우저에서는 iframe과 교차 창(cross-window) 보안 고려로 인해 실제 전역 객체(직접 접근할 수 없는) 주변의 Proxy를 참조한다. 이 구분은 일반적인 사용에서 거의 관련이 없지만 알고 있는 것이 중요하다.

명명(Naming)

selfglobal 같은 몇몇 다른 인기 있는 이름 후보들은 기존 코드와의 호환성을 깨뜨릴 가능성 때문에 고려 대상에서 제외되었다. 자세한 내용은 언어 제안서의 "naming" 문서를 참조하라.

globalThis는 문자 그대로 전역 this 값이다. 객체 없이 호출되는 non-strict 함수의 this 값과 같은 값이며, 스크립트의 전역 스코프에서 this의 값이기도 하다.

예제

환경을 가로질러 전역 검색하기

보통 전역 객체는 명시적으로 지정할 필요가 없다. 그 속성들이 자동으로 전역 변수로 접근 가능하기 때문이다.

console.log(window.Math === Math); // true

하지만 전역 객체를 명시적으로 접근해야 하는 경우 중 하나는, 보통 polyfill 목적으로 전역 객체에 쓸 때이다.

globalThis 이전에는 특정 환경의 전역 객체를 얻는 유일한 신뢰할 수 있는 크로스 플랫폼 방법이 Function('return this')()였다. 하지만 이는 일부 설정에서 CSP 위반을 일으키므로, 작성자들은 다음과 같은 분할 정의를 사용했다(원래 core-js 소스에서 약간 수정):

function check(it) {
  // Math is known to exist as a global in every environment.
  return it && it.Math === Math && it;
}

const globalObject =
  check(typeof window === "object" && window) ||
  check(typeof self === "object" && self) ||
  check(typeof global === "object" && global) ||
  // This returns undefined when running in strict mode
  (function () {
    return this;
  })() ||
  Function("return this")();

전역 객체를 얻은 후에는 그 위에 새 전역을 정의할 수 있다. 예를 들어 Intl 구현을 추가하는 경우:

if (typeof globalObject.Intl === "undefined") {
  // No Intl in this environment; define our own on the global scope
  Object.defineProperty(globalObject, "Intl", {
    value: {
      // Our Intl implementation
    },
    enumerable: false,
    configurable: true,
    writable: true,
  });
}

globalThis를 사용할 수 있게 되면 환경을 가로지르는 전역 검색이 더 이상 필요하지 않다:

if (typeof globalThis.Intl === "undefined") {
  Object.defineProperty(globalThis, "Intl", {
    value: {
      // Our Intl implementation
    },
    enumerable: false,
    configurable: true,
    writable: true,
  });
}

명세(Specifications)

  • ECMAScript® 2027 Language Specification — sec-globalthis

브라우저 호환성

baseline 기준 2020년 1월부터 널리 사용 가능하다. 호환성 표는 JavaScript를 활성화해야 볼 수 있다.

참고 자료

  • globalThiscore-js 폴리필
  • globalThis의 es-shims 폴리필
  • this

더 알아보기