YDNJSY Scope & Closures - 4. Around the Global Scope

코스·2020년 11월 23일
0

You Don't Know JS Yet

목록 보기
8/8
post-thumbnail

이 시리즈는 You Don't Know JS Yet (1판인 You Don't Know JS의 개정판) 을 가지고 스터디를 진행하면서 요약 정리한 글입니다. 내용에 대한 퀴즈도 깃헙 리포지토리에 올리고 있으니 참고하시면 더 도움이 되실 것 같습니다. 내용에 대해 오류가 있거나 궁금하신 점이 있다면 댓글 달아주세요!

Why Global Scope?

당연히 JS를 사용하는데 여러 JS 파일을 작성해 사용하는데, JS가 파일들을 묶는 큰 하나의 런타임 컨텍스트를 만드는 방법은 2가지가 있습니다.

책에서는 총 3가지를 이야기하면서, 한가지 방법으로 처리 과정에서 (webpack과 같은) 번들러를 사용해 여러 파일들을 하나의 파일로 통합해 처리하는 방법을 소개했습니다. 다만 이는 JS에서 직접적으로 처리하지는 않기 때문에 이 분류에서 제외했습니다.

ES Modules를 사용하면 각각의 모듈이 개별적으로 JS 환경에 들어갑니다. 이후 모듈을 사용할 때엔 import 키워드를 사용해 가져올 수 있습니다. 이때는 모듈의 스코프를 공유할 필요가 없기 때문에 더욱 독립적으로 모듈을 다룰 수 있습니다.

var moduleOne = (function one(){
  // ..
})();

var moduleTwo = (function two(){
  // ..
  function callModuleOne() {
    moduleOne.someMethod();
  }
  // ..
})();

ES Module을 사용하지 않거나, 번들러를 사용하지 않을때 파일간 스코프를 만들기 위해선 결국 전역 스코프 (Global scope)을 사용해야 합니다. 위 코드와 같이 moduleOnemoduleTwo처럼 선언을 한다면 값이 Global Scope로 가게 됩니다. 다만 이렇게 사용하는 것을 남용하면 예외가 많이 발생하기 때문에 적절히 사용해야 합니다.

Where Exactly is this Global Scope?

Browser

var studentName = "Sungwoo";

function hello() {
  console.log(`Hello, ${ window.studentName }!`);
}

window.hello();	// Hello, Sungwoo!

JS는 HTML 안에서 <script> 태그를 사용해도 사용이 가능한데, 그 상황에서 사용된 변수들은 window 전역변수에 저장됩니다.

window.something = 42;
let something = "Kyle";

console.log(something);		// Kyle
console.log(window.something);	// 42

지난 챕터에서 다뤘던 Shadowing도 window 변수에 적용되기 때문에 일반적으로는 꺼내올 수 없고 이때 window를 사용해 특정지을 수 있습니다.

Developer Tools Console/REPL

이전에 이야기했듯 개발자 콘솔이나 REPL과 같은 환경에서는 JS의 기능을 100프로 활용할 수 없다고 이야기드렸는데, 대표적인 예시가 바로 전역 스코프입니다. 개발 콘솔에서 선언한 변수들은 전역 스코프에 들어가지만 이 전역 스코프는 가상으로 구현된 스코프이기 때문에 의도한 대로 작동하지 않을 수 있습니다.

ES Modules

var studentName = "Kyle";

function hello() {
  console.log(`Hello, ${ studentName }!`);
}

export hello;	// module-global

ESM을 통해 여러 파일을 하나의 스코프로 관리할 수 있다고 언급했는데, 이때엔 studentName과 hello는 전역 스코프에 있지 않습니다. 대신 import를 통해 가져올 수 있습니다. ESM은 전역 스코프에 최소한으로 의존할 수 있도록 도와줍니다.

Node

global.studentName = "Kyle";

function hello() {
  console.log(`Hello, ${ studentName }!`);
}

hello();	// Hello, Kyle!

ESM과 마찬가지로 Node 환경에서는 선언만 하는 경우 전역 스코프에 변수를 선언할 수 없습니다. 이때 Node에서의 전역변수인 global을 활용하면 전역 스코프에 변수를 넣을 수 있습니다.

Global This

const theGlobalScopeObject =
  (typeof globalThis != "undefined") ? globalThis :
  (typeof global != "undefined") ? global :
  (typeof window != "undefined") ? window :
  (typeof self != "undefined") ? self :
  (new Function("return this"))();

ES2020에서부터 GlobalThis가 추가되면서 웹에서 사용한 window와 Node에서 활용한 global을 한번에 사용할 수 있습니다. 위 코드는 GlobalThis의 폴리필입니다.

profile
잡다한거 하는 개발자

0개의 댓글