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

1. 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 ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

1.1. TDZ์˜ ์˜ํ–ฅ์„ ๋ฐ›๋Š” ๊ตฌ๋ฌธ

1.1.1. const ๋ณ€์ˆ˜

์ด์ „์— ๋ณด์•˜๋“ฏ์ด, const ๋ณ€์ˆ˜๋Š” ์„ ์–ธ ๋ฐ ์ดˆ๊ธฐํ™” ์ „ ์ค„๊นŒ์ง€ TDZ์— ์žˆ์Šต๋‹ˆ๋‹ค.

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

const ๋ณ€์ˆ˜๋Š” ์„ ์–ธํ•œ ํ›„์— ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

const pi = 3.14;


// Works!
pi; // => 3.14

1.1.2. let ๋ณ€์ˆ˜

let๋„ ์„ ์–ธ ์ „ ์ค„๊นŒ์ง€ TDZ์˜ ์˜ํ–ฅ์„ ๋ฐ›์Šต๋‹ˆ๋‹ค.

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

count = 10;

๋‹ค์‹œ, let ๋ณ€์ˆ˜๋„ ์„ ์–ธ ์ดํ›„์— ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

let count;

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

// Works!
count; // => 10

1.1.3. 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'

1.1.4. 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'

1.1.5. ๊ธฐ๋ณธ ํ•จ์ˆ˜ ๋งค๊ฐœ๋ณ€์ˆ˜(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

1.2. 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 ๊ตฌ๋ฌธ์ด ํ˜ธ์ด์ŠคํŒ… ๋˜๊ธฐ ๋•Œ๋ฌธ์—, ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ ์‹œ์ž‘ ๋ถ€๋ถ„์—์„œ ๋””ํŽœ๋˜์‹œ ๋ชจ๋“ˆ์„ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

1.3. TDZ์—์„œ typeof ์—ฐ์‚ฐ์ž์˜ ๋™์ž‘

typeof ์—ฐ์‚ฐ์ž๋Š” ๋ณ€์ˆ˜๊ฐ€ ํ˜„์žฌ ์Šค์ฝ”ํ”„ ์•ˆ์— ์„ ์–ธ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด์„œ, notDefined ๋ณ€์ˆ˜๋Š” ์„ ์–ธ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์ด ๋ณ€์ˆ˜์— typeof ์—ฐ์‚ฐ์ž๋ฅผ ์ ์šฉํ•˜๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

typeof notDefined; // => 'undefined'

๋ณ€์ˆ˜๊ฐ€ ์„ ์–ธ๋˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์—, typeof notDefined๋Š” undefined๋กœ ํ‰๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ TDZ์˜ ๋ณ€์ˆ˜์—์„œ typeof ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ์— ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

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

1.4. ํ˜„์žฌ ์Šค์ฝ”ํ”„ ์•ˆ์—์„œ 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๋Š” ๋‚ด๋ถ€ ์Šค์ฝ”ํ”„์—์„œ๋งŒ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

2. 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

๋ณต์‚ฌํ–ˆ์Šต๋‹ˆ๋‹ค!