Chapter 4: Aroundthe Global Scope - hochan222/Everything-in-JavaScript GitHub Wiki

Why Global Scope?

Execution Context in JS

JS ์—”์ง„์ด single runtime context์—์„œ ์–ด๋–ป๊ฒŒ ํ•ฉ์ณ์งˆ๊นŒ? Browser-executed applications์—์„œ 3๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

  1. ES ๋ชจ๋“ˆ์„ ์ง์ ‘ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ํŒŒ์ผ๋“ค์€ JS enviroment์— ๊ฐœ๋ณ„์ ์œผ๋กœ ๋ถˆ๋Ÿฌ์™€์ง€๊ณ , ๊ฐ ๋ชจ๋“ˆ์€ ์ ‘๊ทผํ•ด์•ผํ•˜๋Š” ๋‹ค๋ฅธ ๋ชจ๋“ˆ์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
  2. ๋นŒ๋“œ ํ”„๋กœ์„ธ์Šค์—์„œ ๋ฒˆ ๋“ค๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ์ผ๋ฐ˜์ ์œผ๋กœ ๋ชจ๋“  ํŒŒ์ผ์ด ๋ธŒ๋ผ์šฐ์ €์™€ JS ์—”์ง„์— ์ „๋‹ฌ๋˜๊ธฐ ์ „์— ํ•จ๊ป˜ ์—ฐ๊ฒฐ๋˜์–ด ํ•˜๋‚˜์˜ ํฐ ํŒŒ์ผ ๋งŒ ์ฒ˜๋ฆฌ๋œ๋‹ค.
  3. ๋งŒ์•ฝ ์–ด๋Š๊ฒƒ๋„ ์•„๋‹ˆ๋ฉด global scope๊ฐ€ ๊ทธ ์—ญํ• ์„ ํ•œ๋‹ค.

module.js

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

var moduleTwo = (function two(){
  // ..

  function callModuleOne() { 
    moduleOne.someMethod();
  }

  // ..
})();

์ด๊ฑฐ๋ž‘ ๋ฐ‘์— ๋ณ„๋„์˜ ๋‘ ํŒŒ์ผ์ด๋ž‘ ๋˜‘๊ฐ™์ด ์ „์—ญ์œผ๋กœ ์ฒ˜๋ฆฌ๋œ๋‹ค.

moduleOne.js

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

moduleTwo.js

var moduleTwo = (function two(){
  // ..

  function callModuleOne() { 
    moduleOne.someMethod();
  }

  // ..
})();

๋ธŒ๋ผ์šฐ์ € ํ™˜๊ฒฝ์—์„œ ๊ฐœ๋ณ„์ ์œผ๋กœ ๋ถˆ๋Ÿฌ์™€์ง€๋Š” ๊ฒฝ์šฐ ์ „์—ญ ๋ณ€์ˆ˜๊ฐ€ ์œ ์ผํ•œ ๊ณต์œ  ๋ฆฌ์†Œ์Šค์ด๋‹ค.

์ „์—ญ๋ฒ”์œ„๋Š” ๊ทธ์™ธ์—๋„ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

  • built-ins ์ œ๊ณต
    • primitives: undefined, null, Infinity, NaN
    • natives: Date(), Object(), String(), etc.
    • global functions: eval(), parseInt(), etc.
    • namespaces: Math, Atomics, JSON
    • friends of JS: Intl, WebAssembly
  • JS ์—”์ง„์„ ํ˜ธ์ŠคํŒ…ํ•˜๋Š” ํ™˜๊ฒฝ์—์„œ ๊ทธ๊ฒƒ์˜ built-ins ์ œ๊ณต
    • console (and its methods)
    • the DOM (window, document, etc)
    • timers (setTimeout(..), etc)
    • web platform APIs: navigator, history, geolocation, WebRTC, etc.

Node๋„ ์ „์—ญ์œผ๋กœ ์—ฌ๋Ÿฌ๊ฐ€์ง€๋ฅผ ์ œ๊ณตํ•˜์ง€๋งŒ require(), __dirname, module, URL(๋“ฑ๋“ฑ)๋“ค์€ ๊ธฐ์ˆ ์ ์œผ๋กœ global scope์— ์žˆ์ง€ ์•Š๋Š”๋‹ค.

Where Exactly is this Global Scope?

global scope๋Š” ํ•ญ์ƒ ์ตœ์ƒ๋‹จ scope(ํŒŒ์ผ์˜ ๊ฐ€์žฅ ๋ฐ”๊นฅ์ชฝ ๋ถ€๋ถ„) ์ผ๊นŒ..? JS environment์— ๋”ฐ๋ผ ๋‹ค๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ๋„ ์žˆ๋‹ค.

Browser โ€œWindowโ€

var studentName = "Kyle";

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

hello();
// Hello, Kyle!

์ผ๋ฐ˜์ ์œผ๋กœ ์›นํŽ˜์ด์ง€ ํ™˜๊ฒฝ์—์„œ window ๋ฅผ ํ†ตํ•ด global scope์— ์ ‘๊ทผ ํ•  ์ˆ˜ ์žˆ๋‹ค.

var studentName = "Kyle";

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

hello();
// Hello, Kyle!

๊ทธ๋Ÿฌ๋‚˜ ํ•ญ์ƒ ๋ชจ๋“  JS ํ™˜๊ฒฝ์—์„œ window๋ฅผ ํ†ตํ•ด ์ ‘๊ทผ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค.

Globals Shadowing Globals

์ „์žฅ์—์„œ ์„ค๋ช…ํ•œ ์‰๋„์ž‰์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒ ํ•  ์ˆ˜ ์žˆ๋‹ค.

window.something = 42;

let something = "Kyle";

console.log(something);
// Kyle

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

let ์„ ์–ธ์€ ์ „์—ญ ๋ณ€์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•˜์ง€๋งŒ ์ „์—ญ ๊ฐ์ฒด ์†์„ฑ์€ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š๋Š”๋‹ค.

์ด ๋ฌธ์ œ๋ฅผ ํ”ผํ•˜๊ธฐ์œ„ํ•ด ์ „์—ญ ๋ณ€์ˆ˜๋Š” ํ•ญ์ƒ var, ๊ทธ์™ธ ๋ธ”๋ก ๋ณ€์ˆ˜๋Š” let๊ณผ const๋ฅผ ์‚ฌ์šฉํ•˜์ž.

DOM Globals

DOM์—์„œ ์ „์—ญ ๋ฒ”์œ„์˜ ๋†€๋ผ์šด ๋™์ž‘ ์ค‘ ํ•˜๋‚˜๋Š” id ์†์„ฑ์ด์žˆ๋Š” DOM ์š”์†Œ๊ฐ€ ์ด๋ฅผ ์ฐธ์กฐํ•˜๋Š” ์ „์—ญ ๋ณ€์ˆ˜๋ฅผ ์ž๋™์œผ๋กœ ๋งŒ๋“ ๋‹ค. ๊ทธ์™ธ์—๋Š” window[]๋กœ ์ ‘๊ทผ ํ•  ์ˆ˜ ์žˆ๋‹ค.

<ul id="my-todo-list">
  <li id="first">Write a book</li> ..
</ul>
first;
// <li id="first">..</li>

window["my-todo-list"];
// <ul id="my-todo-list">..</ul>

Whatโ€™s in a (Window) Name?

var name = 42; 

console.log(name, typeof name);
// "42" string

name์€ window.name์œผ๋กœ window์— ๋ฏธ๋ฆฌ ์ •์˜๋ผ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ์šฐ๋ฆฌ๋Š” ์ˆซ์ž๋ฅผ ๋„ฃ์—ˆ์ง€๋งŒ ๋ฌธ์ž์—ด๋กœ ์ €์žฅ๋˜๋Š” ๊ธฐ์ดํ•œ ํ˜„์ƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์ด๋Ÿฐ ๋“œ๋ฌธ ๋ช‡๋ช‡ ๊ฐ€์ง€๋ฅผ ์ œ์™ธํ•˜๊ณ  ์ •์ƒ ์ž‘๋™ํ•œ๋‹ค.

Web Workers

Web Workers๋Š” ๋ธŒ๋ผ์šฐ์ € JS ๋™์ž‘์„ ๊ธฐ๋ฐ˜์œผ๋กœํ•˜๋Š” ์›น ํ”Œ๋žซํผ ํ™•์žฅ์œผ๋กœ, JS ํŒŒ์ผ์ด ๊ธฐ๋ณธ JS ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•˜๋Š” ์Šค๋ ˆ๋“œ์™€ ์™„์ „ํžˆ ๋ณ„๊ฐœ์˜ ์Šค๋ ˆ๋“œ (์šด์˜ ์ฒด์ œ ์ธก๋ฉด)์—์„œ ์‹คํ–‰๋  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.

Web Worker ํ”„๋กœ๊ทธ๋žจ์€ ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฒฝ์Ÿ ์กฐ๊ฑด ๋ฐ ๊ธฐํƒ€ ์˜ค๋ฅ˜๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๊ธฐ๋ณธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์Šค๋ ˆ๋“œ์™€์˜ ํ†ต์‹ ์ด ์ œํ•œ๋œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, Web Worker๋Š” DOM์— ์•ก์„ธ์Šค ํ•  ์ˆ˜ ์—†๋‹ค. (๋‹จ, ๋„ค๋น„๊ฒŒ์ดํ„ฐ๊ฐ™์€ ์ผ๋ถ€ ์›น API๋Š” ๊ฐ€๋Šฅ)

Web Worker๋Š” ์™„์ „ํžˆ ๋ถ„๋ฆฌ๋œ ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ ์ทจ๊ธ‰๋ผ์„œ ๋ฉ”์ธ JS ํ”„๋กœ๊ทธ๋žจ๊ณผ ์ „์—ญ ๋ฒ”์œ„๋ฅผ ๊ณต์œ ํ•˜์ง€ ์•Š๋Š”๋‹ค. DOM ์•ก์„ธ์Šค๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ „์—ญ ๋ฒ”์œ„์˜ ์ฐฝ ๋ณ„์นญ์ด ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค. Web Worker์—์„œ ์ „์—ญ ๊ฐœ์ฒด ์ฐธ์กฐ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ self๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋งŒ๋“ค์–ด์ง„๋‹ค.

var studentName = "Kyle"; 
let studentID = 42;

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

self.hello();
// Hello, Kyle!

self.studentID;
// undefined

Developer Tools Console/REPL

Developer Tools Console/REPL์€ ๊ธฐ์กด ์ฒ˜๋ฆฌ๋ณด๋‹ค ๊ฐ„ํŽธํ™”๋๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์ œ ๋™์ž‘๊ณผ ์œ ์‚ฌํ•˜๊ฒŒ ์ž‘๋™ํ•œ๋‹ค. ์ฃผ๋กœ ๋‹ค์Œ ์„ธ๊ฐ€์ง€์—์„œ ์ฐจ์ด๊ฐ€ ๋‚  ์ˆ˜ ์žˆ๋‹ค.

  • global scope ๋™์ž‘
  • ํ˜ธ์ด์ŠคํŒ…
  • ๊ฐ€์žฅ ๋ฐ–์—์„œ ์‚ฌ์šฉ๋  ๋•Œ let๊ณผ const์˜ ๋™์ž‘ (๋ธ”๋ก ๋ฒ”์œ„ ์„ ์–ธ์ž)

๋”ฐ๋ผ์„œ Developer Tools Console/REPL์€ JS์—์„œ ์„ธ์„ธํ•˜๊ณ  ๋ฏธ๋ฌ˜ํ•œ ๋™์ž‘์„ ํ™•์ธ ํ•  ๋•Œ ์ ํ•ฉํ•œ ํˆด์€ ์•„๋‹ˆ๋‹ค.

ES6์—์„œ module pattern์„ ์ง€์›ํ•œ๋‹ค. (export๋ฅผ ์‚ฌ์šฉํ•ด ์กฐ์ •๋œ๋‹ค.)

var studentName = "Kyle";

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

hello();
// Hello, Kyle!

export hello;

studentName๊ณผ hello์€ ์ „์—ญ ๋ณ€์ˆ˜๊ฐ€ ์•„๋‹ˆ๋‹ค.

Node

Node๋Š” Node ํ”„๋กœ์„ธ์Šค๋ฅผ ์‹œ์ž‘ํ•˜๋Š” ๊ธฐ๋ณธ ํŒŒ์ผ์„ ํฌํ•จํ•˜์—ฌ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋ชจ๋“  ๋‹จ์ผ .js ํŒŒ์ผ์„ ๋ชจ๋“ˆ๋กœ ์ทจ๊ธ‰ํ•œ๋‹ค. Node ํ”„๋กœ๊ทธ๋žจ์˜ ์ตœ์ƒ์œ„ ๋ ˆ๋ฒจ์ด ์‹ค์ œ๋กœ๋Š” ์ „์—ญ ๋ฒ”์œ„๊ฐ€ ์•„๋‹ˆ๋‹ค. ์ตœ๊ทผ ES ๋ชจ๋“ˆ์— ๋Œ€ํ•œ ์ง€์›์„ ์ถ”๊ฐ€ํ–ˆ์ง€๋งŒ, Node๋Š” ์ฒ˜์Œ๋ถ€ํ„ฐ ๋‹ค์Œ๊ณผ ๊ฐ™์€ "CommonJS"๋ผ๋Š” ๋ชจ๋“ˆ ํ˜•์‹์„ ์ง€์›ํ–ˆ๋‹ค.

function Module(module,require,__dirname,...) { 
  var studentName = "Kyle";

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

  module.exports.hello = hello; 
}

Node๋Š” require ()์™€ ๊ฐ™์€ ๋งŽ์€ "์ „์—ญ"์„ ์ •์˜ํ•˜์ง€๋งŒ ์‹ค์ œ๋กœ ์ „์—ญ ๋ฒ”์œ„์˜ ์‹๋ณ„์ž (์ „์—ญ ๊ฐ์ฒด์˜ ์†์„ฑ๋„ ์•„๋‹˜)๊ฐ€ ์•„๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ Module (..) ํ•จ์ˆ˜ ์„ ์–ธ์— ๋‚˜์—ด๋œ ๋งค๊ฐœ ๋ณ€์ˆ˜์™€ ๋น„์Šทํ•˜๊ฒŒ ๋ชจ๋“  ๋ชจ๋“ˆ์˜ ๋ฒ”์œ„์— ์‚ฝ์ž…ํ•œ๋‹ค.

Node์—์„œ ์‹ค์ œ ์ „์—ญ ๋ณ€์ˆ˜๋Š” global์„ ํ†ตํ•ด ์ •์˜ํ•œ๋‹ค.

global.studentName = "Kyle";

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

hello();
// Hello, Kyle!

module.exports.hello = hello;

Global This

ES2020์—์„œ JS๋Š” ๋งˆ์นจ๋‚ด globalThis๋ผ๋Š” ์ „์—ญ ๋ฒ”์œ„ ๊ฐœ์ฒด์— ๋Œ€ํ•œ ํ‘œ์ค€ํ™” ๋œ ์ฐธ์กฐ๋ฅผ ์ •์˜ํ–ˆ๋‹ค.
๋˜ํ•œ, ํด๋ฆฌํ•„๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ๋‹ค.

const theGlobalScopeObject =
    (typeof globalThis != "undefined") ? globalThis : 
    (typeof global != "undefined") ? global : 
    (typeof window != "undefined") ? window : 
    (typeof self != "undefined") ? self :
    (new Function("return this"))();
โš ๏ธ **GitHub.com Fallback** โš ๏ธ