article thumbnail image
Published 2022. 7. 21. 02:08

TDZ(Temporal Dead Zone)λŠ” 무엇인가?

const λ³€μˆ˜λ₯Ό μ„ μ–Έν•˜κ³  μ΄ˆκΈ°ν™”ν•˜λ©΄ λ³€μˆ˜μ— μ ‘κ·Όν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ˜ˆμƒν•œλŒ€λ‘œ λ™μž‘ν•©λ‹ˆλ‹€.

const white = '#FFFFFF';
white; // => '#FFFFFF'

μ΄λ²ˆμ—λŠ” μ„ μ–Έ 전에 white λ³€μˆ˜μ— 접근해보도둝 ν•˜κ² μŠ΅λ‹ˆλ‹€.

white; // throws `ReferenceError`
const white = '#FFFFFF';

white

const white = '#FFFFFF' ꡬ문 μ „ μ€„κΉŒμ§€, white λ³€μˆ˜λŠ” TDZ에 μžˆμŠ΅λ‹ˆλ‹€.

TDZ에 μžˆλŠ” white λ³€μˆ˜μ— μ ‘κ·Όν•˜κ²Œ 되면 , ReferenceError: Cannot access 'white' before initialization μžλ°”μŠ€ν¬λ¦½νŠΈ μ—λŸ¬κ°€ λ°œμƒν•©λ‹ˆλ‹€.

TDZ의 영ν–₯을 λ°›λŠ” ꡬ문

const λ³€μˆ˜

이전에 λ³΄μ•˜λ“―μ΄, const λ³€μˆ˜λŠ” μ„ μ–Έ 및 μ΄ˆκΈ°ν™” μ „ μ€„κΉŒμ§€ TDZ에 μžˆμŠ΅λ‹ˆλ‹€.

// Does not work!
pi; // throws `ReferenceError`
const pi = 3.14;

const λ³€μˆ˜λŠ” μ„ μ–Έν•œ 후에 μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.

const pi = 3.14;


// Works!
pi; // => 3.14

let λ³€μˆ˜

let도 μ„ μ–Έ μ „ μ€„κΉŒμ§€ TDZ의 영ν–₯을 λ°›μŠ΅λ‹ˆλ‹€.

// Does not work!
count; // throws `ReferenceError`
let count;

count = 10;

λ‹€μ‹œ, let λ³€μˆ˜λ„ μ„ μ–Έ 이후에 μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.

let count;

// Works!
count; // => undefined
count = 10;

// Works!
count; // => 10

class ꡬ문

머리말 λΆ€λΆ„μ—μ„œ λ³΄μ•˜λ“―μ΄, μ„ μ–Έ μ „μ—λŠ” classλ₯Ό μ‚¬μš©ν•  수 μ—†μŠ΅λ‹ˆλ‹€.

// Does not work!
const myNissan = new Car('red'); // throws `ReferenceError`

class Car {
  constructor(color) {
    this.color = color;
  }
}

이 μ˜ˆμ œκ°€ λ™μž‘ν•˜λ €λ©΄, 클래슀λ₯Ό μ„ μ–Έν•œ 후에 μ‚¬μš©ν•˜λ„λ‘ μˆ˜μ •ν•©λ‹ˆλ‹€.

class Car {
  constructor(color) {
    this.color = color;
  }
}

// Works!
const myNissan = new Car('red');
myNissan.color; // => 'red'

constructor() λ‚΄λΆ€μ˜ super()

λΆ€λͺ¨ 클래슀λ₯Ό μƒμ†λ°›μ•˜λ‹€λ©΄, μƒμ„±μž μ•ˆμ—μ„œ super()λ₯Ό ν˜ΈμΆœν•˜κΈ° μ „κΉŒμ§€ this 바인딩은 TDZ에 μžˆμŠ΅λ‹ˆλ‹€.

class MuscleCar extends Car {
  constructor(color, power) {
    this.power = power;
    super(color);
  }
}

// Does not work!
const myCar = new MuscleCar(‘blue’, ‘300HP’); // `ReferenceError`

이 μ½”λ“œλ₯Ό 보면 constructor() μ•ˆμ—μ„œ super()κ°€ 호좜되기 μ „κΉŒμ§€ thisλ₯Ό μ‚¬μš©ν•  수 μ—†μŠ΅λ‹ˆλ‹€.

TDZλŠ” μΈμŠ€ν„΄μŠ€λ₯Ό μ΄ˆκΈ°ν™”ν•˜κΈ° μœ„ν•΄ λΆ€λͺ¨ 클래슀의 μƒμ„±μžλ₯Ό ν˜ΈμΆœν•  것을 μ œμ•ˆν•©λ‹ˆλ‹€. λΆ€λͺ¨ 클래슀의 μƒμ„±μžλ₯Ό ν˜ΈμΆœν•˜κ³  μΈμŠ€ν„΄μŠ€κ°€ μ€€λΉ„λ˜λ©΄ μžμ‹ ν΄λž˜μŠ€μ—μ„œ this 값을 λ³€κ²½ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

class MuscleCar extends Car {
  constructor(color, power) {
    super(color);
    this.power = power;
  }
}

// Works!
const myCar = new MuscleCar('blue', '300HP');
myCar.power; // => '300HP'

κΈ°λ³Έ ν•¨μˆ˜ λ§€κ°œλ³€μˆ˜(Default Function Parameter)

κΈ°λ³Έ λ§€κ°œλ³€μˆ˜λŠ” κΈ€λ‘œλ²Œκ³Ό ν•¨μˆ˜ μŠ€μ½”ν”„ μ‚¬μ΄μ˜ 쀑간 μŠ€μ½”ν”„(intermidiate scope)에 μœ„μΉ˜ν•©λ‹ˆλ‹€. κΈ°λ³Έ λ§€κ°œλ³€μˆ˜ λ˜ν•œ TDZ μ œν•œμ΄ μžˆμŠ΅λ‹ˆλ‹€.

const a = 2;
function square(a = a) {
  return a * a;
}
// Does not work!
square(); // throws `ReferenceError`

κΈ°λ³Έ λ§€κ°œλ³€μˆ˜ aλŠ” μ„ μ–Έ 전에 a = a ν‘œν˜„μ‹μ˜ 였λ₯Έμͺ½μ—μ„œ μ‚¬μš©λ˜μ—ˆμŠ΅λ‹ˆλ‹€. aμ—μ„œ μ°Έμ‘° μ—λŸ¬κ°€ λ°œμƒν•©λ‹ˆλ‹€.

κΈ°λ³Έ λ§€κ°œλ³€μˆ˜λŠ” μ„ μ–Έ 및 μ΄ˆκΈ°ν™” λ‹€μŒμ— μ‚¬μš©λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€. 이 경우 initκ³Ό 같은 λ‹€λ₯Έ λ³€μˆ˜λ‘œ μ„ μ–Έν•˜μ—¬ μ‚¬μš©ν•©λ‹ˆλ‹€.

const init = 2;
function square(a = init) {
  return a * a;
}
// Works!
square(); // => 4

var, function, import ꡬ문

μœ„μ—μ„œ μ„€λͺ…ν•œ 것듀과 λ°˜λŒ€λ‘œ var, function 선언은 TDZ에 영ν–₯을 받지 μ•ŠμŠ΅λ‹ˆλ‹€. 이것듀은 ν˜„μž¬ μŠ€μ½”ν”„μ—μ„œ ν˜Έμ΄μŠ€νŒ… λ©λ‹ˆλ‹€.

var λ³€μˆ˜λŠ” μ„ μ–Έν•˜κΈ° 전에 μ ‘κ·Όν•˜λ©΄, undefinedλ₯Ό μ–»κ²Œ λ©λ‹ˆλ‹€.

// Works, but don't do this!
value; // => undefined
var value;

κ·ΈλŸ¬λ‚˜ ν•¨μˆ˜λŠ” μ„ μ–Έλœ μœ„μΉ˜μ™€ 상관없이 λ™μΌν•˜κ²Œ ν˜ΈμΆœλ©λ‹ˆλ‹€.

// Works!
greet('World'); // => 'Hello, World!'
function greet(who) {
  return `Hello, ${who}!`;
}

// Works!
greet('Earth'); // => 'Hello, Earth!'

당신은 ν•¨μˆ˜ κ΅¬ν˜„λ³΄λ‹€ ν˜ΈμΆœμ— 더 관심이 있기 λ•Œλ¬Έμ— μ’…μ’… ν•¨μˆ˜ μ„ μ–Έ 전에 ν˜ΈμΆœν•˜κ²Œ λ©λ‹ˆλ‹€. ν•¨μˆ˜ μ„ μ–Έ 전에 ν˜ΈμΆœν•΄λ„ μ—λŸ¬κ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ” μ΄μœ λŠ” ν˜Έμ΄μŠ€νŒ… λ•Œλ¬Έμž…λ‹ˆλ‹€.

ν₯미둜운 점으둜 import λͺ¨λ“ˆ μ—­μ‹œ ν˜Έμ΄μŠ€νŒ… λ©λ‹ˆλ‹€.

// Works!
myFunction();
import { myFunction } from './myModule';

import ꡬ문이 ν˜Έμ΄μŠ€νŒ… 되기 λ•Œλ¬Έμ—, μžλ°”μŠ€ν¬λ¦½νŠΈ 파일 μ‹œμž‘ λΆ€λΆ„μ—μ„œ λ””νŽœλ˜μ‹œ λͺ¨λ“ˆμ„ κ°€μ Έμ˜€λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.

TDZμ—μ„œ typeof μ—°μ‚°μžμ˜ λ™μž‘

typeof μ—°μ‚°μžλŠ” λ³€μˆ˜κ°€ ν˜„μž¬ μŠ€μ½”ν”„ μ•ˆμ— μ„ μ–Έλ˜μ—ˆλŠ”μ§€ 확인할 λ•Œ μœ μš©ν•©λ‹ˆλ‹€.

예λ₯Ό λ“€μ–΄μ„œ, notDefined λ³€μˆ˜λŠ” μ„ μ–Έλ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. 이 λ³€μˆ˜μ— typeof μ—°μ‚°μžλ₯Ό μ μš©ν•˜λ©΄ μ—λŸ¬κ°€ λ°œμƒν•©λ‹ˆλ‹€.

typeof notDefined; // => 'undefined'

λ³€μˆ˜κ°€ μ„ μ–Έλ˜μ§€ μ•Šμ•˜κΈ° λ•Œλ¬Έμ—, typeof notDefinedλŠ” undefined둜 ν‰κ°€ν•©λ‹ˆλ‹€.
κ·ΈλŸ¬λ‚˜ TDZ의 λ³€μˆ˜μ—μ„œ typeof μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•˜λ©΄ λ‹€λ₯΄κ²Œ λ™μž‘ν•©λ‹ˆλ‹€. λ‹€μŒκ³Ό 같은 κ²½μš°μ— μ—λŸ¬κ°€ λ°œμƒν•©λ‹ˆλ‹€.

typeof variable; // throws `ReferenceError`
let variable;

ν˜„μž¬ μŠ€μ½”ν”„ μ•ˆμ—μ„œ TDZ λ™μž‘

TDZ은 선언문이 μ‘΄μž¬ν•˜λŠ” μŠ€μ½”ν”„ λ²”μœ„ μ•ˆμ—μ„œ λ³€μˆ˜μ— 영ν–₯을 μ€λ‹ˆλ‹€.

예제λ₯Ό 보게되면,

function doSomething(someVal) {
  // Function scope
  typeof variable; // => undefined
  if (someVal) {
    // Inner block scope
    typeof variable; // throws `ReferenceError`
    let variable;
  }
}
doSomething(true);

이 μ½”λ“œλŠ” 2개의 μŠ€μ½”ν”„λ₯Ό κ°€μ§‘λ‹ˆλ‹€.

  • ν•¨μˆ˜ μŠ€μ½”ν”„
  • let λ³€μˆ˜κ°€ μ„ μ–Έλœ λ‚΄λΆ€ 블둝 μŠ€μ½”ν”„

ν•¨μˆ˜ μŠ€μ½”ν”„μ—μ„œ typeof variableλŠ” undefined둜 ν‰κ°€λ©λ‹ˆλ‹€. μ—¬κΈ°μ„œλŠ” let variable ꡬ문의 TDZ에 영ν–₯을 주지 μ•ŠμŠ΅λ‹ˆλ‹€.

typeof variable ꡬ문의 λ‚΄λΆ€ μŠ€μ½”ν”„μ—μ„œλŠ” μ„ μ–Έ 전에 λ³€μˆ˜λ₯Ό μ‚¬μš©ν•˜λ©΄ ReferenceError: Cannot access 'variable' before initialization μ—λŸ¬κ°€ λ°œμƒν•©λ‹ˆλ‹€. TDZλŠ” λ‚΄λΆ€ μŠ€μ½”ν”„μ—μ„œλ§Œ μ‘΄μž¬ν•©λ‹ˆλ‹€.

References

 

TDZ을 λͺ¨λ₯Έ 채 μžλ°”μŠ€ν¬λ¦½νŠΈ λ³€μˆ˜λ₯Ό μ‚¬μš©ν•˜μ§€ 말라

κ°„λ‹¨ν•œ μ§ˆλ¬Έμ„ ν•˜λ‚˜ ν•˜κ² λ‹€. μ•„λž˜ μ½”λ“œ μŠ€λ‹ˆνŽ«μ—μ„œ μ—λŸ¬κ°€ λ°œμƒν• κΉŒ? 첫 번째 μ½”λ“œλŠ” μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•œ λ‹€μŒ 클래슀λ₯Ό μ„ μ–Έν•œλ‹€.

ui.toast.com

 

Don't Use JavaScript Variables Without Knowing Temporal Dead Zone

Temporal Dead Zone forbids the access of variables and classes before declaration in JavaScript.

dmitripavlutin.com

λ³΅μ‚¬ν–ˆμŠ΅λ‹ˆλ‹€!