globalThis 폴리필로 보는 자바스크립트 모든 환경에서 this 접근
각 환경마다 전역 객체에 접근하는 방식이 달라 개발자들을 괴롭혔는데요. 이런 문제를 해결하기 위해 es2020에 등장한 것이 바로 globalThis
입니다.
기존 환경의 복잡성
아래 환경들을 고려해야하는 모든 환경을 지원하기 위해서는 생각보다 까다로운데요.
실행 환경
브라우저
브라우저 워커(Web Worker, Service Worker)
브라우저 확장 프로그램
Node.js
자바스크립트 엔진(V8, Webkit)
실행 모드
sloppy mode
strict mode
자바스크립트 모듈
globalThis의 등장
globalThis
는 전역 스코프의 this
값을 일관되게 제공합니다.
실행 환경별 globalThis의 동작
브라우저
globalThis === window // true
globalThis === frames // true
globalThis === self // true
웹 워커
// window, frames는 워커에서 사용 불가
globalThis === self // true
Node.js
globalThis === global // true
자바스크립트 엔진
// window, frames, self, global 사용 불가
globalThis === this // true
실행 모드별 globalThis의 동작
모듈 스코프는 글로벌 스코프의 this
를 숨기기 때문에 최상단에서 this
는 undefined
가 됩니다
console.log(this); // undefined
console.log(globalThis); // 전역 객체
strict mode에서도 마찬가지로 함수 내부의 this
는 undefined
가 됩니다.
globalThis이전 솔루션
// Function 생성자 활용
globalThis === Function('return this')();
// eval 사용
var global = eval('this');
브라우저의 CSP(Content Security Policy)와 같이 eval()
을 비활성화하는 환경에서는 사용할 수 없었습니다.
globalThis 폴리필
직접 구현
const getGlobal = () => {
if (typeof globalThis !== 'undefined') return globalThis;
if (typeof self !== 'undefined') return self;
if (typeof window !== 'undefined') return window;
if (typeof global !== 'undefined') return global;
throw new Error('전역 객체를 찾을 수 없습니다');
};
라이브러리 속 구현
// core-js (https://github.com/zloirock/core-js)
'use strict';
var check = function (it) {
return it && it.Math === Math && it;
};
// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
module.exports =
// eslint-disable-next-line es/no-global-this -- safe
check(typeof globalThis == 'object' && globalThis) ||
check(typeof window == 'object' && window) ||
// eslint-disable-next-line no-restricted-globals -- safe
check(typeof self == 'object' && self) ||
check(typeof global == 'object' && global) ||
check(typeof this == 'object' && this) ||
// eslint-disable-next-line no-new-func -- fallback
(function () { return this; })() || Function('return this')();
// @ungap/global-this (https://github.com/ungap/global-this)
(function (Object) {
typeof globalThis !== 'object' && (
this ?
get() :
(Object.defineProperty(Object.prototype, '_T_', {
configurable: true,
get: get
}), _T_)
);
function get() {
var global = this || self;
global.globalThis = global;
delete Object.prototype._T_;
}
}(Object));
마무리
globalThis
는 자바스크립트의 복잡한 환경 차이를 해결하는 최적의 솔루션이라고 생각합니다. 만약 레거시 환경을 지원해야 한다면 폴리필을 사용해야겠지만, 가능하다면 globalThis
를 사용하는 것이 가장 안전할 것 같습니다.
참고
Last updated