Frontend/JavaScript

[ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ(JavaScript) ] var, let, const ๋ณ€์ˆ˜ ์ฐจ์ด์ ๊ณผ ํ˜ธ์ด์ŠคํŒ…(hoisting), TDZ(Temporal Dead Zone), ์Šค์ฝ”ํ”„

YWTechIT 2021. 7. 31. 22:49
728x90

๐Ÿ“ var, let, const ๋ณ€์ˆ˜ ์ฐจ์ด์ ๊ณผ ํ˜ธ์ด์ŠคํŒ…(hoisting)

์ผ๋ฐ˜์ ์œผ๋กœ var , let , const ๋ผ๊ณ  ํ•  ๋•Œ์˜ ๊ธฐ๋ณธ์ ์ธ ์ฐจ์ด์ ์€ ๋Œ€๋žต์ ์œผ๋กœ๋‚˜๋งˆ ์•Œ๊ณ  ์žˆ์„ ๊ฒƒ์ด๋‹ค. (์–ด๋ ดํ’‹์ด ์ž‘์„ฑํ•œ ๋‚˜์˜ ๊ธ€) ๊ฐ„๋žตํ•˜๊ฒŒ ๋งํ•˜๋ฉด var ์™€ let ์€ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜๊ณ  ๋ณ€์ˆ˜๋ฅผ ํ• ๋‹นํ•œ ์ดํ›„์—๋„ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์ง€๋งŒ(์ •ํ™•ํžˆ๋Š” var ๋Š” ์žฌ์„ ์–ธ ๋ฐ ์žฌํ• ๋‹น์ด ๊ฐ€๋Šฅํ•˜๊ณ , let ์€ ์žฌ์„ ์–ธ์€ ๋ถˆ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ์žฌํ• ๋‹น์€ ๊ฐ€๋Šฅํ•˜๋‹ค.) const๋Š” ํ•œ๋ฒˆ ํ• ๋‹นํ•œ ๊ฐ’์€ ๋‹ค์‹œ ๋ฐ”๊ฟ€ ์ˆ˜ ์—†๋‹ค.

 

์ด๋ ‡๊ฒŒ var ๋ณ€์ˆ˜์˜ ๋›ฐ์–ด๋‚œ ์œ ์—ฐ์„ฑ๋งŒํผ ๋‹จ์ ๋„ ์žˆ๋Š”๋ฐ,var ๋ฌธ๋ฒ•์€ ์Šค์ฝ”ํ”„์˜ ๋ฒ”์œ„(์ •ํ™•ํ•˜๊ฒŒ๋Š” ํ•จ์ˆ˜ ์Šค์ฝ”ํ”„)๊ฐ€ ๋„“์–ด์„œ ์˜๋„์น˜ ์•Š์€ ๋ฒ„๊ทธ์˜ ๋ฐœ์ƒ์›์ธ์ด ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ES6 ๋ฌธ๋ฒ•์— let, const ๋ฌธ๋ฒ•์ด ์ถ”๊ฐ€๋˜๋ฉด์„œ var ๋Œ€์‹  let, const ์‚ฌ์šฉ์„ ๊ถŒ์žฅํ•˜๊ณ  ์žˆ๋‹ค.

 

๊ทธ๋ ‡๋‹ค๋ฉด ๋ณ€์ˆ˜์™€ ์Šค์ฝ”ํ”„์˜ ๋ฒ”์œ„๋Š” ์–ด๋–ค ๊ด€๊ณ„๊ฐ€ ์žˆ์„๊นŒ? ์ด๋ฅผ ์•Œ๊ธฐ ์œ„ํ•ด์„œ๋Š” JS ์˜ ๊ธฐ๋ณธ ํŠน์„ฑ์ธ ํ˜ธ์ด์ŠคํŒ…(hoisting)์„ ์•Œ์•„์•ผ ํ•˜๋Š”๋ฐ, ํ˜ธ์ด์ŠคํŒ…์ด๋ž€ ๋ณ€์ˆ˜ ๋ฐ ํ•จ์ˆ˜ ์„ ์–ธ์ด ๋ฌผ๋ฆฌ์ ์œผ๋กœ ์ž‘์„ฑํ•œ ์ฝ”๋“œ์˜ ์ƒ๋‹จ์œผ๋กœ ์˜ฎ๊ฒจ์ง€๋Š” ๊ฒƒ์ด์ง€๋งŒ, ์‹ค์ œ๋กœ๋Š” ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒƒ์„ ๋งํ•œ๋‹ค. JS ์—์„œ๋Š” ํ•จ์ˆ˜ ์„ ์–ธ์„ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅํ•˜๋Š” ๋ฐฉ์‹์„ ์ฑ„ํƒํ•˜๋Š”๋ฐ ์ด๊ฒƒ์˜ ์žฅ์ ์€ ์ฝ”๋“œ์—์„œ ์„ ์–ธํ•˜๊ธฐ ์ „์— ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค. ๋‹ค์Œ์˜ ์˜ˆ๋ฅผ ๋ณด์ž.

printMyname("์•ˆ์˜์šฐ")

function printMyName(name){
    console.log(`์ œ ์ด๋ฆ„์€ ${name}์ž…๋‹ˆ๋‹ค.`)
}

๐Ÿ‘‰๐Ÿฝ ์ œ ์ด๋ฆ„์€ ์•ˆ์˜์šฐ์ž…๋‹ˆ๋‹ค.

 

์ด์ฒ˜๋Ÿผ printMyName ํ•จ์ˆ˜๋ฅผ ์„ ์–ธํ•˜๊ธฐ ์ „์ธ๋ฐ๋„ ๋ถˆ๊ตฌํ•˜๊ณ  printMyName์„ ํ˜ธ์ถœํ•˜๋ฉด ์ •์ƒ์ ์œผ๋กœ ์ปดํŒŒ์ผํ•˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ, ํ˜ธ์ด์ŠคํŒ…์€ ํ•จ์ˆ˜ ๋‚ด๋ถ€์— ๊ตญํ•œํ•˜์ง€ ์•Š๊ณ  ํ•จ์ˆ˜ ์™ธ๋ถ€์—์„œ๋„ ์ผ์–ด๋‚˜๋Š”๋ฐ, ์—ฌ๊ธฐ์„œ ์ฃผ์˜ํ•  ์ ์€ ๋ณ€์ˆ˜ ์„ ์–ธ์€ ํ˜ธ์ด์ŠคํŒ…๋˜์ง€๋งŒ, ๋ณ€์ˆ˜ ํ• ๋‹น์€ ํ˜ธ์ด์ŠคํŒ…์ด ์ผ์–ด๋‚˜์ง€ ์•Š๋Š”๋‹ค. ๋‹ค์Œ์˜ ์˜ˆ๋ฅผ ๋ณด์ž.

// ์‹ค์ œ์ฝ”๋“œ
console.log(name);  // undefined
var name = "์•ˆ์˜์šฐ";
console.log(name);  // ์•ˆ์˜์šฐ

// ๋‚ด๋ถ€ ์ž‘๋™ ์ฝ”๋“œ
var name;    // isHoisting
console.log(name);    // undefined
name = "์•ˆ์˜์šฐ";    // assignment
console.log(name);    // ์•ˆ์˜์šฐ

 

๊ฐ™์€ ์ƒํ™ฉ์—์„œ let ์€ ๋‹ค๋ฅด๊ฒŒ ์ถœ๋ ฅ๋˜๋Š”๋ฐ, ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ReferenceError: Cannot access 'name' before initialization ์˜ค๋ฅ˜๊ฐ€ ๋œฌ๋‹ค.

console.log(name);  // ReferenceError: Cannot access 'name' before initialization 
let name = "์•ˆ์˜์šฐ";
console.log(name);  // ์•ˆ์˜์šฐ
728x90

๐Ÿ“ TDZ(Temporal Dead Zone), ์Šค์ฝ”ํ”„

var ๋ณ€์ˆ˜์™€ ๋‹ฌ๋ฆฌ let, const ๋Š” ํ˜ธ์ด์ŠคํŒ…์ด ๋˜์ง€ ์•Š์•„์„œ ์ด๋Ÿฐ ์—๋Ÿฌ๊ฐ€ ๋œจ๋Š” ๊ฒƒ์ผ๊นŒ? ๊ทธ๋ ‡์ง€ ์•Š๋‹ค. let, const ๋ณ€์ˆ˜๋„ ํ˜ธ์ด์ŠคํŒ…๋œ๋‹ค. ํ•˜์ง€๋งŒ var ๋ณ€์ˆ˜์™€๋Š” ๋‹ค๋ฅด๊ฒŒ let , const ๋ณ€์ˆ˜๋Š” TDZ(Temporal Dead Zone) ์˜ ์˜ํ–ฅ์„ ๋ฐ›๋Š”๋‹ค. ์ด์ „ ์ฝ”๋“œ์—์„œ TDZ ์˜ ์˜์—ญ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. TDZ(Temporal Dead Zone)๋ž€ ์‹œ๊ฐ„์  ์‚ฌ๊ฐ์ง€๋Œ€๋ฅผ ์˜๋ฏธํ•˜๋Š”๋ฐ, ๋ณ€์ˆ˜๊ฐ€ ๋ธ”๋ก ์‹œ์ž‘๋ถ€ํ„ฐ ์ดˆ๊ธฐํ™”๊ฐ€ ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€๋ฅผ TDZ ๋ผ๊ณ  ์ผ์ปซ๋Š”๋‹ค. ์‰ฝ๊ฒŒ ๋งํ•ด์„œ ๋ณ€์ˆ˜์— ์‹ค์งˆ์ ์ธ ๊ฐ’์„ ํ• ๋‹นํ•˜๊ธฐ ์ „์—” ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š”๋ฐ TDZ ๋ฅผ ์„ค์ •ํ•˜๋Š” ์ด์œ ๋Š” ์ฝ”๋“œ๋ฅผ ์˜ˆ์ธก ๊ฐ€๋Šฅํ•˜๊ณ , ์ž ์žฌ์ ์ธ ๋ฒ„๊ทธ๋ฅผ ์ค„์ด๊ธฐ ์œ„ํ•จ์ด๋‹ค.

console.log(name);  // TDZ(Temporal Dead Zone)
let name = "์•ˆ์˜์šฐ";
console.log(name);  // ์•ˆ์˜์šฐ

 

JS ์—์„œ ๋ณ€์ˆ˜์˜ ์ƒ์„ฑ๊ณผ์ •์€ 3๋‹จ๊ณ„์— ๊ฑธ์ณ์„œ ์ •์˜๋˜๋Š”๋ฐ, ๋ณ€์ˆ˜ ์„ ์–ธ → ๋ณ€์ˆ˜ ์ดˆ๊ธฐํ™” → ๋ณ€์ˆ˜ ํ• ๋‹น์˜ ์ˆœ์„œ๋กœ ์ •์˜๋œ๋‹ค. ์—ฌ๊ธฐ์„œ var let , const ๋Š” ๊ฐ๊ฐ ๋‹ค๋ฅธ ๊ณผ์ •์œผ๋กœ ๋ณ€์ˆ˜๊ฐ€ ๋งŒ๋“ค์–ด์ง„๋‹ค.

 

์šฐ์„ , var ๋Š” ์„ ์–ธ ๋‹จ๊ณ„ + ์ดˆ๊ธฐํ™” ๋‹จ๊ณ„๊ฐ€ ๋™์‹œ์— ์ด๋ฃจ์–ด์ง€๊ณ  ์ดํ›„ ํ• ๋‹น ๋‹จ๊ณ„๋ฅผ ๊ฑฐ์นœ๋‹ค. ๋‹ค์Œ์˜ ์ฝ”๋“œ๋ฅผ ๋ณด์ž. ์„ ์–ธํ•˜์ง€๋„ ์•Š์€ name ๊ฐ’์— undefined ๊ฐ€ ์ถœ๋ ฅ๋˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด๋Š” ํ˜ธ์ด ์ŠคํŒ… ๊ณผ์ •์„ ๊ฑฐ์น˜๋ฉด์„œ var ๋ณ€์ˆ˜์˜ ์ƒ์„ฑ + var ์ดˆ๊ธฐํ™” ๊ฐ’ undefined ์ด ๋™์‹œ์— ์ด๋ฃจ์–ด์ง€๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ดํ›„ name = "์•ˆ์˜์šฐ" ๋ผ๋Š” ๊ฐ’์„ ํ• ๋‹นํ•˜๋ฉด ๊ทธ์ œ์•ผ ๋‚ด๊ฐ€ ํ• ๋‹นํ•œ ๊ฐ’์ธ ์•ˆ์˜์šฐ ๊ฐ’์ด ๋‚˜์˜จ๋‹ค.

// ์‹ค์ œ ์ฝ”๋“œ
console.log(name);    // undefined
var name;
name = "์•ˆ์˜์šฐ";
console.log(name);    // ์•ˆ์˜์šฐ

// ๋‚ด๋ถ€ ํ˜ธ์ด์ŠคํŒ…
var name;
console.log(name);    // undefined
name = "์•ˆ์˜์šฐ";
console.log(name);    // ์•ˆ์˜์šฐ

 

๋‹ค์Œ์œผ๋กœ let ์€ ์„ ์–ธ → ์ดˆ๊ธฐํ™” → ํ• ๋‹น ์ˆœ์œผ๋กœ ์ด๋ฃจ์–ด์ง€๋Š”๋ฐ, ๋‹ค์Œ์˜ ์ฝ”๋“œ์—์„œ๋Š” let์ด ํ˜ธ์ด์ŠคํŒ…๋˜๋ฉด์„œ ์„ ์–ธ ๋‹จ๊ณ„๊นŒ์ง€ ์ด๋ฃจ์–ด์กŒ์ง€๋งŒ, ๋ณดํ†ต ์ดˆ๊ธฐํ™” ๋‹จ๊ณ„๋Š” ์‹ค์ œ ์ฝ”๋“œ์— ๋„๋‹ฌํ–ˆ์„ ๋•Œ ์ผ์–ด๋‚˜๊ธฐ ๋•Œ๋ฌธ์— ReferenceError ๊ฐ€ ๋‚˜์˜ค๋Š” ๊ฒƒ์ด๋‹ค.

// ์‹ค์ œ ์ฝ”๋“œ
console.log(name);    // ReferenceError: Cannot access 'name' before initialization
let name;
name = "์•ˆ์˜์šฐ";
console.log(name);    // ์•ˆ์˜์šฐ

// ๋‚ด๋ถ€ ํ˜ธ์ด์ŠคํŒ…
console.log(name);    // TDZ 
let name;
name = "์•ˆ์˜์šฐ";
console.log(name);    // ์•ˆ์˜์šฐ

 

๋งˆ์ง€๋ง‰์œผ๋กœ const ๋Š” ์„ ์–ธ + ์ดˆ๊ธฐํ™” + ํ• ๋‹น ๋ชจ๋‘ ๋™์‹œ์— ์ด๋ฃจ์–ด์ ธ์•ผ ํ•œ๋‹ค. var, let๋Š” ์„ ์–ธ๋งŒ ํ•ด๋‘๊ณ  ๋‚˜์ค‘์— ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•˜์ง€๋งŒ const๋Š” ํ•œ ๋ฒˆ์— ํ• ๋‹น๊นŒ์ง€ ํ•ด์•ผ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

// var
var name;
name = "์•ˆ์˜์šฐ";

// let
let age;
age = 27;

// const
const gender;
gender = "male";    // SyntaxError: Missing initializer in const declaration

 

๋˜, var , let , const ๋ณ€์ˆ˜๋Š” ํ˜ธ์ถœ ๊ฐ€๋Šฅํ•œ ์˜์—ญ(?)์ธ ์Šค์ฝ”ํ”„๊ฐ€ ๊ฐ๊ฐ ์ •ํ•ด์ ธ ์žˆ๋Š”๋ฐ ์—ฌ๊ธฐ์„œ ์Šค์ฝ”ํ”„๋ž€ ํ˜„์žฌ ์‹คํ–‰๋˜๋Š” ์ปจํ…์ŠคํŠธ(context) ์‰ฝ๊ฒŒ ๋งํ•ด ๋ณ€์ˆ˜ ๋˜๋Š” ๋‹ค๋ฅธ ํ‘œํ˜„์‹์ด ํ•ด๋‹น ์Šค์ฝ”ํ”„๋‚ด์— ์žˆ์ง€ ์•Š๋‹ค๋ฉด ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค. ์Šค์ฝ”ํ”„๋Š” ๋˜ํ•œ ๊ณ„์ธต์ ์ธ ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง€๊ธฐ ๋•Œ๋ฌธ์— ํ•˜์œ„ ์Šค์ฝ”ํ”„๋Š” ์ƒ์œ„ ์Šค์ฝ”ํ”„์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋ฐ˜๋Œ€๋Š” ๋ถˆ๊ฐ€ํ•˜๋‹ค.

 

var ๋Š” ํ•จ์ˆ˜ ์Šค์ฝ”ํ”„(function-scoped)์˜ ์˜ํ–ฅ์„, let , const ๋Š” ๋ธ”๋ก ์Šค์ฝ”ํ”„(block-scoped) ์˜ ์˜ํ–ฅ์„ ๋ฐ›๋Š”๋‹ค.

 

var ๋ณ€์ˆ˜๋Š” ์œ ์ผํ•˜๊ฒŒ ํ•จ์ˆ˜ ์Šค์ฝ”ํ”„(function-scoped)์˜ํ–ฅ์„ ๋ฐ›๋Š”๋‹ค๊ณ  ํ–ˆ๋Š”๋ฐ, ์‰ฝ๊ฒŒ ๋งํ•˜๋ฉด ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ๊ฐ’์„ ํ˜ธ์ถœํ• ๋•Œ๋Š” ํ•จ์ˆ˜์™ธ๋ถ€์—์„œ ํ˜ธ์ถœ ํ•  ์ˆ˜ ์—†๊ณ  ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ๋งŒ ํ˜ธ์ถœ ํ•  ์ˆ˜ ์žˆ๊ณ  ๋‹ค๋ฅธ ์กฐ๊ฑด๋ฌธ, ๋ฐ˜๋ณต๋ฌธ ๋“ฑ์—์„œ๋Š” ํ˜ธ์ถœ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. ๋‹ค์Œ ์˜ˆ๋ฅผ ๋ณด์ž.

// ํ•จ์ˆ˜ score ์™ธ๋ถ€์—์„œ var๋ณ€์ˆ˜ ํ˜ธ์ถœ(๋ถˆ๊ฐ€๋Šฅ)
function myName(){
    var name = "์•ˆ์˜์šฐ";    
}
myName();
console.log(name);    // ReferenceError: name is not defined

// ํ•จ์ˆ˜ score ๋‚ด๋ถ€์—์„œ var๋ณ€์ˆ˜ ํ˜ธ์ถœ(๊ฐ€๋Šฅ)
function myName(){
    var name = "์•ˆ์˜์šฐ";    
    console.log(name);   
}

myName();    // ์•ˆ์˜์šฐ

// ์กฐ๊ฑด๋ฌธ ๋ฐ–์—์„œ var๋ณ€์ˆ˜ ํ˜ธ์ถœ(๊ฐ€๋Šฅ)
if (true){
    var age = 27;
}

console.log(age);    // 27

 

let, const ๋Š” ๋ธ”๋ก ์Šค์ฝ”ํ”„์˜ ์˜ํ–ฅ์„ ๋ฐ›๋Š”๋‹ค. ์—ฌ๊ธฐ์„œ ๋ธ”๋ก์ด๋ž€ ์ค‘๊ด„ํ˜ธ ๋‚ด๋ถ€ (if, for , while , try/catch ๋ฌธ ๋“ฑ)์„ ๋œปํ•œ๋‹ค.

// if๋ฌธ ๋‚ด๋ถ€์—์„œ ํ˜ธ์ถœ(๊ฐ€๋Šฅ)
if(true){
    let age = 27;
    console.log(age);    // 27
}

// if๋ฌธ ์™ธ๋ถ€์—์„œ ํ˜ธ์ถœ(๋ถˆ๊ฐ€๋Šฅ)
if(true){
    let age = 27;
}
console.log(age);    // ReferenceError: age is not defined

// function ๋‚ด๋ถ€์—์„œ ํ˜ธ์ถœ(๊ฐ€๋Šฅ)
function showMyAge(){
    const age = 27;
        console.log(age);
}

showMyAge();    // 27

// function ์™ธ๋ถ€์—์„œ ํ˜ธ์ถœ(๋ถˆ๊ฐ€๋Šฅ)
function showMyAge(){
    const age = 27;
}

showMyAge();
console.log(age);    // ReferenceError: age is not defined

์ง€๊ธˆ๊นŒ์ง€ var, let ,const ๋ณ€์ˆ˜๋“ค์˜ ์ฐจ์ด์ ๊ณผ ํ˜ธ์ด์ŠคํŒ…(hoisting), TDZ, ์Šค์ฝ”ํ”„์— ๋Œ€ํ•ด์„œ ๋ฐฐ์› ๋‹ค. var ๋Š” ์ด์ œ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ , let ,const ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋Š” ์˜ˆ์ธก ๊ฐ€๋Šฅํ•˜๊ณ  ์ž ์žฌ์ ์ธ bug ๋ฅผ ์ค„์ด๊ธฐ ์œ„ํ•œ ๊ฒƒ์ž„์„ ๊ธฐ์–ตํ•˜์ž.

 

- Reference

  1. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ค‘๊ธ‰ ๊ฐ•์ขŒ #1 - ๋ณ€์ˆ˜, ํ˜ธ์ด์ŠคํŒ…, TDZ(Temporal Dead Zone)
  2. MDN
๋ฐ˜์‘ํ˜•