9. ν˜Έμ΄μŠ€νŒ…

9-1. ν˜Έμ΄μŠ€νŒ…μ΄λž€?

9-1-1. μ •μ˜μ™€ κ°œλ…

ν•¨μˆ˜ μ•ˆμ— μžˆλŠ” 선언듀을 λͺ¨λ‘ λŒμ–΄μ˜¬λ €μ„œ ν•΄λ‹Ή ν•¨μˆ˜ 유효 λ²”μœ„(scope)의 μ΅œμƒλ‹¨μ— μ„ μ–Έν•˜λŠ” 것 같이 λ™μž‘ν•˜λŠ” ν˜„μƒμ„ λ§ν•œλ‹€. μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진은 μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜κΈ° μ „ μ‹€ν–‰ κ°€λŠ₯ν•œ μ½”λ“œλ₯Ό ν˜•μƒν™”ν•˜κ³  κ΅¬λΆ„ν•˜λŠ” κ³Όμ •(μ‹€ν–‰μ»¨ν…μŠ€νŠΈλ₯Ό μœ„ν•œ κ³Όμ •)을 κ±°μΉœλ‹€. μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλ₯Ό μœ„ν•œ κ³Όμ •μ—μ„œ λͺ¨λ“  μ„ μ–Έ(var, let, const, function, class)을 μŠ€μ½”ν”„μ— λ“±λ‘ν•œλ‹€. μ½”λ“œ μ‹€ν–‰ μ „ 이미 λ³€μˆ˜(var)와 ν•¨μˆ˜μ„ μ–Έμ΄ μ €μž₯λ˜μ–΄ 있기 λ•Œλ¬Έμ— μ°Έμ‘°/호좜이 λ¨Όμ € λ‚˜μ™€λ„ 였λ₯˜ 없이 λ™μž‘ν•œλ‹€. ν˜Έμ΄μŠ€νŒ…μ΄λΌλŠ” μš©μ–΄λ₯Ό μžλ°”μŠ€ν¬λ¦½νŠΈ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ— μ˜ν•œ μœ„μ— μ„€λͺ…ν•œ ν˜„μƒμ„ ν˜Έμ΄μŠ€νŒ…μ΄λΌκ³  λΆ€λ₯Έλ‹€λŠ” κ²ƒμœΌλ‘œ μ΄ν•΄ν•˜λ©΄ λ˜κ² λ‹€. κ·Έ ν˜„μƒμ΄λž€ 선언이 μ½”λ“œ 싀행보닀 λ¨Όμ € λ©”λͺ¨λ¦¬μ— μ €μž₯λ˜λŠ” κ³Όμ •μœΌλ‘œ μΈν•œ ν˜„μƒμ„ λ§ν•œλ‹€.

9-1-2. ν˜Έμ΄μŠ€νŒ…μ΄ λ°œμƒν•˜λŠ” 이유

var a = 2; λŠ” ν•˜λ‚˜μ˜ ꡬ문처럼 λ³΄μ΄μ§€λ§Œ, μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진은 κ·Έλ ‡κ²Œ 보지 μ•ŠλŠ”λ‹€. 'var a'와 β€˜a = 2'λΌλŠ” λ³„κ°œμ˜ ꡬ문으둜 보고, 첫 λ²ˆμ§ΈλŠ” 컴파일러 λ‹¨κ³„μ—μ„œ μ²˜λ¦¬ν•˜κ³ , 두 번째 ꡬ문은 μ‹€ν–‰ λ‹¨κ³„μ—μ„œ μ²˜λ¦¬ν•œλ‹€. 이 μ˜λ―ΈλŠ” μŠ€μ½”ν”„μ˜ λͺ¨λ“  선언문은 μ‹€ν–‰ 전에 λ¨Όμ € μ²˜λ¦¬λœλ‹€λŠ” 점이닀.
πŸ’‘
ν˜Έμ΄μŠ€νŒ…μ΄ λ°œμƒν•˜λŠ” μ΄μœ μ— λŒ€ν•΄ 더 μžμ„Ένžˆ μ•Œμ•„λ³΄μž.
 
μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ λ ‰μ‹œμ»¬ ν™˜κ²½(Lexical Environment)은 ν™˜κ²½ λ ˆμ½”λ“œ(Environment Record)와 μ™ΈλΆ€ λ ‰μ‹œμ»¬ ν™˜κ²½ μ°Έμ‘° μ»΄ν¬λ„ŒνŠΈ(Outer LexicalEnvironment Reference)둜 κ΅¬μ„±λœλ‹€.
Environment Record λŠ” 유효 λ²”μœ„ μ•ˆμ˜ μ‹λ³„μžμ™€ 결과값을 λ°”μΈλ“œ ν•΄μ„œ κΈ°λ‘ν•˜λŠ” μ˜μ—­μ΄λ‹€. 여기에 ν•¨μˆ˜ μ„ μ–Έ, λ³€μˆ˜λͺ… 등이 λ‹΄κΈ°λŠ”λ°, μ»¨ν…μŠ€νŠΈ λ‚΄λΆ€ 전체λ₯Ό μ²˜μŒλΆ€ν„° λκΉŒμ§€ ν›‘μœΌλ©΄μ„œ μˆœμ„œλŒ€λ‘œ μˆ˜μ§‘ν•œλ‹€. λ”°λΌμ„œ μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진은 μ½”λ“œκ°€ μ‹€ν–‰λ˜κΈ° 전에도 이미 ν•΄λ‹Ή ν™˜κ²½μ— μ†ν•œ μ½”λ“œ λ³€μˆ˜λͺ…듀을 μ•Œκ³  있기 λ•Œλ¬Έμ— ν˜Έμ΄μŠ€νŒ…μ΄ μΌμ–΄λ‚˜λŠ” 것이닀.

9-2. λ³€μˆ˜ ν˜Έμ΄μŠ€νŒ…

9-2-1. var ν‚€μ›Œλ“œμ™€ ν˜Έμ΄μŠ€νŒ…

λ³€μˆ˜(var)선언이 ν˜Έμ΄μŠ€νŒ…μœΌλ‘œ 인해 선언이 λŒμ–΄μ˜¬λ €μ Έμ„œ 였λ₯˜κ°€ λ‚˜μ§€ μ•ŠλŠ”λ‹€.
console.log(text); // μ„ μ–Έ, μ΄ˆκΈ°ν™” ok text = 'Hanamon!'; // μ„ μ–Έ, μ΄ˆκΈ°ν™”, ν• λ‹Ή ok var text;

9-2-2. letκ³Ό const ν‚€μ›Œλ“œμ™€ ν˜Έμ΄μŠ€νŒ…

μ•„λž˜ μ½”λ“œμ—μ„œ ν˜Έμ΄μŠ€νŒ… λ•Œλ¬Έμ— 선언이 λŒμ–΄μ˜¬λ €μ‘Œμ§€λ§Œ, μ΄ˆκΈ°ν™” μ•ˆ 된 μƒνƒœμ—μ„œ μ°Έμ‘°ν•΄μ„œ 였λ₯˜κ°€ λ‚œλ‹€.
console.log(text); // μ„ μ–Έ ok / μ΄ˆκΈ°ν™” x //(λ©”λͺ¨λ¦¬ 곡간 확보와 undefined둜 μ΄ˆκΈ°ν™”) μ°Έμ‘° λΆˆκ°€λŠ₯ -> μ—λŸ¬ λ°œμƒ let text; // μ—¬κΈ°μ„œ μ΄ˆκΈ°ν™” 단계가 μ‹€ν–‰λœλ‹€.
const text; // μ• μ΄ˆμ— const ν‚€μ›Œλ“œλ‘œ μž¬ν• λ‹Ή λΆˆκ°€λŠ₯! κ·Έλž˜μ„œ μ„ μ–Έκ³Ό λ™μ‹œμ— ν• λ‹Ήν•΄μ•Ό 함
πŸ’‘
TDZ(Temporal Dead Zone)
TDZλŠ” μΌμ‹œμ μΈ μ‚¬κ°μ§€λŒ€λ‘œ, λ³€μˆ˜λ₯Ό μ‚¬μš©ν•˜λŠ” 것을 λΉ„ν—ˆμš© ν•˜λŠ” κ°œλ…μƒμ˜ 곡간이닀.
TDZ에 μžˆλŠ” 값에 μ ‘κ·Όν•˜κ²Œ 되면 ReferenceErrorκ°€ λ°œμƒν•œλ‹€
μ •ν™•νžˆλŠ” const, let이 ν˜Έμ΄μŠ€νŒ…μ΄ λ°œμƒν•˜μ§€ μ•ŠλŠ” 것이 μ•„λ‹ˆλ‹€. 선언문을 톡해 λͺ¨λ“  μ‹λ³„μž(λ³€μˆ˜, ν•¨μˆ˜, 클래슀 λ“±)λŠ” ν˜Έμ΄μŠ€νŒ…λœλ‹€.
κ·ΈλŸ¬λ‚˜ varκ³Ό λ‹€λ₯΄κ²Œ μ΄ˆκΈ°ν™”λ˜κΈ° μ „κΉŒμ§€ TDZ에 머물러있기 λ•Œλ¬Έμ— ν˜Έμ΄μŠ€νŒ…μ΄ λ°œμƒν•˜μ§€ μ•ŠλŠ” κ²ƒμ²˜λŸΌ 보이며 μ°Έμ‘°κ°€ λΆˆκ°€λŠ₯ν•˜λ‹€.

9-3. ν•¨μˆ˜ ν˜Έμ΄μŠ€νŒ…

9-3-1. ν•¨μˆ˜ 선언식과 ν•¨μˆ˜ ν‘œν˜„μ‹μ˜ 차이

ν•¨μˆ˜ 선언식은 ν•¨μˆ˜ 이름과 ν•¨κ»˜ μ„ μ–Έλ˜μ–΄ ν˜Έμ΄μŠ€νŒ… 되며, μ–΄λ””μ„œλ“  ν˜ΈμΆœν•  수 μžˆλ‹€. ν•¨μˆ˜ ν‘œν˜„μ‹μ€ λ³€μˆ˜μ— ν• λ‹Ήλœ ν•¨μˆ˜λ‘œ, λ³€μˆ˜ ν˜Έμ΄μŠ€νŒ…μ΄ λ°œμƒν•˜λ―€λ‘œ λ³€μˆ˜κ°€ μ„ μ–Έλ˜κΈ° μ „μ—λŠ” ν˜ΈμΆœν•  수 μ—†λ‹€.
// ν•¨μˆ˜ ν‘œν˜„μ‹ function getName() { console.log('name'); } // ν•¨μˆ˜ μ„ μ–Έλ¬Έ var name = function() { console.log('name'); };

9-3-2. ν•¨μˆ˜ μ„ μ–Έμ‹μ˜ ν˜Έμ΄μŠ€νŒ…

ν•¨μˆ˜ 선언식은 전체가 ν˜Έμ΄μŠ€νŒ… 되기 λ•Œλ¬Έμ— ν•¨μˆ˜λ₯Ό μ„ μ–Έν•˜κΈ° 전에도 ν˜ΈμΆœν•  수 μžˆλ‹€.

9-3-3. ν•¨μˆ˜ ν‘œν˜„μ‹μ˜ ν˜Έμ΄μŠ€νŒ…

ν•¨μˆ˜ ν‘œν˜„μ‹μ€ λ³€μˆ˜κ°€ ν˜Έμ΄μŠ€νŒ… λ˜μ§€λ§Œ ν•¨μˆ˜ μžμ²΄λŠ” ν˜Έμ΄μŠ€νŒ… λ˜μ§€ μ•ŠμœΌλ―€λ‘œ λ³€μˆ˜κ°€ μ„ μ–Έλ˜κΈ° 전에 ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λ©΄ 였λ₯˜κ°€ λ°œμƒν•œλ‹€.
count(); var count = function() { console.log('countλŠ” 1이닀.'); }
μœ„ μ½”λ“œλŠ” count()호좜 ν›„, var countλ₯Ό μ„ μ–Έν•˜λ©° ν•¨μˆ˜λ₯Ό λ‹΄μ•˜λ‹€. varλŠ” ν˜Έμ΄μŠ€νŒ…μ˜ 영ν–₯을 λ°›μœΌλ―€λ‘œ μœ„λ‘œ λŒμ–΄μ˜¬λ €μ§€κ³  var count; κ°€ κ°€μž₯ λ¨Όμ € μ‹€ν–‰λœλ‹€. κ·Έ ν›„λ‘œ count()κ°€ 호좜되면 μœ„μ— μ„ μ–Έν•œ countκ°€ ν˜ΈμΆœλ˜λ―€λ‘œ λ³€μˆ˜λ₯Ό ν˜ΈμΆœν•˜λŠ” 격이 λœλ‹€.
var count; // undefined count(); // countλŠ” ν•¨μˆ˜κ°€ μ•„λ‹Œλ° μ™œ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜μ§€? -> typeError var count = function() { console.log('countλŠ” 1이닀.'); }
λ§Œμ•½ varλŒ€μ‹  let λ˜λŠ” constλ₯Ό 썼닀면 Type Errorκ°€ μ•„λ‹Œ Reference Errorκ°€ λ°œμƒν•  것이닀.(ν˜Έμ΄μŠ€νŒ…μ˜ 영ν–₯을 λ°›μ§€ μ•ŠκΈ° λ•Œλ¬Έμ΄λ‹€.)

9-4. 클래슀의 ν˜Έμ΄μŠ€νŒ…

9-4-1. 클래슀의 ν˜Έμ΄μŠ€νŒ…

ν΄λž˜μŠ€λŠ” varν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•œ λ³€μˆ˜μ²˜λŸΌ ν˜Έμ΄μŠ€νŒ… λ˜μ§€ μ•Šκ³  let, constν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•œ λ³€μˆ˜μ²˜λŸΌ ν˜Έμ΄μŠ€νŒ… λœλ‹€. λ”°λΌμ„œ 클래슀 μ„ μ–Έλ¬Έ 이전에 μΌμ‹œμ  μ‚¬κ°μ§€λŒ€(Temporal Dead Zone: TDZ)에 λΉ μ§€κΈ° λ•Œλ¬Έμ— ν˜Έμ΄μŠ€νŒ…μ΄ λ°œμƒν•˜μ§€ μ•ŠλŠ” κ²ƒμ²˜λŸΌ λ™μž‘ν•œλ‹€
const Foo = ''; { // ν˜Έμ΄μŠ€νŒ…μ΄ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ ''κ°€ 좜λ ₯λ˜μ–΄μ•Ό ν•œλ‹€. console.log(Foo); // ReferenceError: Cannot access 'Foo' before initialization class Foo {} }
μ •λ¦¬ν•˜λ©΄ ν˜Έμ΄μŠ€νŒ…μ€ var, let, const, function, classν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•œ λͺ¨λ“  선언문에 μ μš©λœλ‹€. λ‹€μ‹œ 말해, 선언문을 톡해 λͺ¨λ“  μ‹λ³„μž(λ³€μˆ˜, ν•¨μˆ˜, 클래슀 λ“±)λŠ” ν˜Έμ΄μŠ€νŒ… λœλ‹€. λͺ¨λ“  선언문은 λŸ°νƒ€μž„ 이전에 λ¨Όμ € μ‹€ν–‰λ˜κΈ° λ•Œλ¬Έμ΄λ‹€.