๐Ÿ’ป์šฉ๋‡ฝ ๊ฐœ๋ฐœ ๋…ธํŠธ๐Ÿ’ป
article thumbnail
๋ฐ˜์‘ํ˜•

[JavaScript] ํ˜ธ์ด์ŠคํŒ…(hoisting)์ด ๋„๋Œ€์ฒด ๋ญ˜๊นŒ? ์‰ฝ๊ฒŒ ์ดํ•ดํ•˜๊ธฐ

๐Ÿ“– ๋“ค์–ด๊ฐ€๋ฉฐ

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ์ฝ”๋“œ์˜ ์‹คํ–‰ ์ˆœ์„œ์™€ ์Šค์ฝ”ํ”„๋ฅผ ์ดํ•ดํ•˜๋Š” ๋ฐ ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ•˜๋Š” ์ค‘์š”ํ•œ ๊ฐœ๋… ์ค‘ ํ•˜๋‚˜์ธ ํ˜ธ์ด์ŠคํŒ…(hoisting)์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

ํ˜ธ์ด์ŠคํŒ…(hoisting)์ด๋ž€ โ“

ํ˜ธ์ด์ŠคํŒ…์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์ด ์Šคํฌ๋ฆฝํŠธ๋ฅผ ํ•ด์„ํ•˜๊ณ  ์‹คํ–‰ํ•˜๋Š” ๊ณผ์ •์—์„œ, ๋ณ€์ˆ˜๋‚˜ ํ•จ์ˆ˜, ํด๋ž˜์Šค ์„ ์–ธ์„ ์ฝ”๋“œ์˜ ๋งจ ์œ„๋กœ '๋Œ์–ด์˜ฌ๋ฆฌ๋Š”' ๊ฒƒ๊ณผ ๊ฐ™์€ ํ˜„์ƒ์„ ๋งํ•ฉ๋‹ˆ๋‹ค.

๋ณดํ†ต ํ˜ธ์ด์ŠคํŒ…์— ๋Œ€ํ•œ ์„ค๋ช…์„ ๋ณด๋ฉด '๋Œ์–ด์˜ฌ๋ ค์ง„๋‹ค'๋ผ๊ณ  ๋Œ€๋ถ€๋ถ„ ์„ค๋ช…์ด ๋˜์–ด ์žˆ๋Š”๋ฐ ํ˜ธ์ด์ŠคํŒ…์ด ์‹ค์ œ๋กœ ์ฝ”๋“œ๋ฅผ ๋ฌผ๋ฆฌ์ ์œผ๋กœ ์ตœ์ƒ๋‹จ์œผ๋กœ ์˜ฎ๊ธฐ๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.

์ด๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์˜ ๋‚ด๋ถ€ ๋™์ž‘ ๋ฐฉ์‹์„ ์„ค๋ช…ํ•˜๋Š” ๊ฐœ๋…์ผ ๋ฟ์ž…๋‹ˆ๋‹ค.

ํ˜ธ์ด์ŠคํŒ…์€ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ์˜ ์ƒ์„ฑ ๋‹จ๊ณ„์—์„œ ์ผ์–ด๋‚ฉ๋‹ˆ๋‹ค.

์‹คํ–‰ ์ปจํ…์ŠคํŠธ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜๋Š” ํ™˜๊ฒฝ์„ ๋งํ•ฉ๋‹ˆ๋‹ค.
์ƒ์„ฑ ๋‹จ๊ณ„์—์„œ๋Š” ๋ณ€์ˆ˜ ๊ฐ์ฒด๊ฐ€ ๋งŒ๋“ค์–ด์ง€๊ณ , ์Šค์ฝ”ํ”„ ์ฒด์ธ์ด ํ˜•์„ฑ๋˜๋ฉฐ, this ๊ฐ’์ด ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค.
๋ณ€์ˆ˜ ๊ฐ์ฒด ๋‚ด๋ถ€์—๋Š” ์ธ์ž, ๋‚ด๋ถ€ ๋ณ€์ˆ˜, ๋‚ด๋ถ€ ํ•จ์ˆ˜ ๋“ฑ์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๋ณ€์ˆ˜

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ๋ณ€์ˆ˜๋Š” var, let, const ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ณ€์ˆ˜ ์ƒ์„ฑ ๋‹จ๊ณ„

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์ด ์‹คํ–‰ ์ปจํ…์ŠคํŠธ Lexical Environment์— ๋ณ€์ˆ˜๋ฅผ ๋“ฑ๋กํ•˜๋Š” ๊ณผ์ •์—์„œ ์ด 3๊ฐ€์ง€ ๋‹จ๊ณ„๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

1. ์„ ์–ธ(Declaration) ๋‹จ๊ณ„

ํŠน์ • ์ด๋ฆ„์˜ ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ณผ์ •์ž…๋‹ˆ๋‹ค.

์ด ๋‹จ๊ณ„์—์„œ๋Š” ๋ฉ”๋ชจ๋ฆฌ์— ๋ณ€์ˆ˜๋ฅผ ์œ„ํ•œ ๊ณต๊ฐ„์ด ํ™•๋ณด๋˜๋ฉฐ, ์ด ๊ณต๊ฐ„์€ ๋ณ€์ˆ˜ ์ด๋ฆ„์œผ๋กœ ์ฐธ์กฐ๋  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

2. ์ดˆ๊ธฐํ™”(Initalization) ๋‹จ๊ณ„

์„ ์–ธ๋œ ๋ณ€์ˆ˜์— ๊ธฐ๋ณธ๊ฐ’์„ ์„ค์ •ํ•˜๋Š” ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค.

ํ•ด๋‹น ๋‹จ๊ณ„์—์„œ ๋ณ€์ˆ˜๋Š” undefined๋กœ ์ดˆ๊ธฐํ™”๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

๋Œ€์‹ , var๋กœ ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋Š” ์„ ์–ธ๊ณผ ๋™์‹œ์— undefined๋กœ ์ดˆ๊ธฐํ™”๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์Šค์ฝ”ํ”„์— ๋ณ€์ˆ˜๋ฅผ ๋“ฑ๋ก(์„ ์–ธ ๋‹จ๊ณ„)ํ•˜๊ณ  ๋ฉ”๋ชจ๋ฆฌ์— ๋ณ€์ˆ˜๋ฅผ ์œ„ํ•œ ๊ณต๊ฐ„์„ ํ™•๋ณดํ•œ ํ›„ undefined๋กœ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค.

๋ฐ˜๋ฉด์—, let๊ณผ const๋กœ ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋Š” ์Šค์ฝ”ํ”„์— ๋ณ€์ˆ˜๋ฅผ ๋“ฑ๋ก(์„ ์–ธ ๋‹จ๊ณ„)ํ•˜์ง€๋งŒ ์ดˆ๊ธฐํ™” ๋‹จ๊ณ„๋Š” ๋ณ€์ˆ˜ ์„ ์–ธ๋ฌธ์— ๋„๋‹ฌํ–ˆ์„ ๋•Œ(์ฝ”๋“œ ์‹คํ–‰ ํ›„) ์ด๋ค„์ง‘๋‹ˆ๋‹ค.

console.log(name); // (์„ ์–ธ + ์ดˆ๊ธฐํ™” ๋œ ์ƒํƒœ)
name = 'yong'; // (์„ ์–ธ + ์ดˆ๊ธฐํ™” + ํ• ๋‹น ๋œ ์ƒํƒœ)
var name;
console.log(name);
// ํ˜ธ์ด์ŠคํŒ… ๋ฐœ์ƒํ•จ
console.log(text); // TDZ(Temporal Dead Zone)์— ์žˆ์–ด์„œ ์ฐธ์กฐ ์—๋Ÿฌ ๋ฐœ์ƒ
let text; // ์„ ์–ธ๋ฌธ์— ๋„๋‹ฌํ•˜์—ฌ ์ดˆ๊ธฐํ™” ๋‹จ๊ณ„ ์‹คํ–‰

3. ํ• ๋‹น(Assignment) ๋‹จ๊ณ„

์ดˆ๊ธฐํ™”๋œ ๋ณ€์ˆ˜์— ํŠน์ • ๊ฐ’์„ ์ง€์ •ํ•˜๋Š” ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค.

var ํ˜ธ์ด์ŠคํŒ…

var๋กœ ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋Š” ํ•จ์ˆ˜ ์Šค์ฝ”ํ”„์—์„œ ํ˜ธ์ด์ŠคํŒ… ๋ฉ๋‹ˆ๋‹ค.

์ฆ‰, ํ•จ์ˆ˜ ๋‚ด๋ถ€ ์–ด๋””์—์„œ๋“  ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ, ์„ ์–ธ ์ „์— ์‚ฌ์šฉํ•ด๋„ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ณ  undefined๊ฐ€ ์ถœ๋ ฅ๋˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

console.log(name); // 'undefined'
var name = 'yong';

var ํ‚ค์›Œ๋“œ์˜ ํŠน์ง•์€ var ํ‚ค์›Œ๋“œ๋กœ ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋Š” ํ˜ธ์ด์ŠคํŒ…์— ์˜ํ•ด ๋งจ ์œ„๋กœ ๋Œ์–ด์˜ฌ๋ ค์งˆ ๋•Œ ์ž๋™์œผ๋กœ undefined ๊ฐ’์œผ๋กœ ์ดˆ๊ธฐํ™”๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์„ ์–ธ๋ฌธ ์ „์— ์ ‘๊ทผ์„ ํ•  ์ˆ˜ ์žˆ๋Š” ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํ˜ธ์ด์ŠคํŒ…์˜ ๋™์ž‘ ๊ณผ์ •์€ ์˜ˆ๋ฅผ ๋“ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

name;
console.log(name);
name = 'yong';

let, const ํ˜ธ์ด์ŠคํŒ…

let๊ณผ const๋กœ ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋„ ํ˜ธ์ด์ŠคํŒ…์ด ๋˜๋Š”๋ฐ, ๋ธ”๋ก ์Šค์ฝ”ํ”„์—์„œ ํ˜ธ์ด์ŠคํŒ…์ด ๋ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ, var ํ‚ค์›Œ๋“œ์™€๋Š” ๋‹ค๋ฅด๊ฒŒ ์„ ์–ธ ์ „์— ์ ‘๊ทผํ•˜๋ ค ํ•˜๋ฉด ์ฐธ์กฐ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋˜๋Š”๋ฐ ์ด๋ฅผ 'TDZ - Temporal Dead Zone (์ผ์‹œ์  ์‚ฌ๊ฐ์ง€๋Œ€)'๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” TDZ์— ๋“ค์–ด๊ฐ€ ์žˆ๋Š” ๊ฒƒ๋“ค์˜ ์ ‘๊ทผ์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

console.log(name); // ReferenceError: Cannot access 'name' before initialization
let name = 'yong';
console.log(age); // ReferenceError: Cannot access 'age' before initialization
const age = 25;
let foo = 1;
{
  console.log(foo); // ReferenceError: Cannot access 'foo' before initialization
  let foo = 2;
  // ๋ธ”๋ก ์Šค์ฝ”ํ”„ ์•ˆ์—์„œ ํ˜ธ์ด์ŠคํŒ…์ด ์ผ์–ด๋‚˜๊ธฐ ๋•Œ๋ฌธ์— ์ฐธ์กฐ ์—๋Ÿฌ ๋ฐœ์ƒ
}

๊ทธ๋ฆฌ๊ณ  let์€ var์™€ ๊ฐ™์ด ์žฌ์„ ์–ธ์ด ํ—ˆ์šฉ์ด ๋˜์ง€๋งŒ,

const๋Š” ์žฌ์„ ์–ธ์ด ํ—ˆ์šฉ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— const ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉ ์‹œ ์„ ์–ธ๊ณผ ๋™์‹œ์— ํ• ๋‹น์„ ํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

// โœ…
let num = 0;
console.log(num) // 0
num = 15;
---------------
// โŒ
const name; // SyntaxError: Missing initializer in const declaration
console.log(name)
---------------
// โœ…
const age = 15;
console.log(age) // 15

var, let, const ์ •๋ฆฌ

var ํ‚ค์›Œ๋“œ๋Š” ํ•จ์ˆ˜ ์Šค์ฝ”ํ”„๋ฅผ ๊ฐ€์ง€๊ณ  ํ˜ธ์ด์ŠคํŒ… ์‹œ undefined๋กœ ์ดˆ๊ธฐํ™”๋˜๊ณ  ๊ฐ™์€ ์Šค์ฝ”ํ”„ ๋‚ด์—์„œ ์žฌ์„ ์–ธ์ด ๊ฐ€๋Šฅํ•œ ๋ฐฉ์‹ ๋“ฑ ๋…ํŠนํ•œ ๋ฐฉ์‹ ๋•Œ๋ฌธ์— ํ˜ผ๋ž€์„ ์ดˆ๋ž˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐ˜๋ฉด์—, let๊ณผ const๋Š” ๋ธ”๋ก ์Šค์ฝ”ํ”„๋ฅผ ๊ฐ€์ง€๋ฏ€๋กœ, ์ฝ”๋“œ๊ฐ€ ๋” ์˜ˆ์ธก์ด ๊ฐ€๋Šฅํ•˜๊ณ  ์ดํ•ดํ•˜๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ, ํ˜„๋Œ€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ฐœ๋ฐœ์—์„œ๋Š” var ๋Œ€์‹ ์— let๊ณผ const๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ถŒ์žฅ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ํ•จ์ˆ˜ ์„ ์–ธ

ํ•จ์ˆ˜์˜ ์„ ์–ธ ๋ฐฉ์‹์—๋Š” ์„ ์–ธ์‹๊ณผ ํ‘œํ˜„์‹์ด ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•จ์ˆ˜ ์„ ์–ธ์‹๊ณผ ํ˜ธ์ด์ŠคํŒ…

ํ•จ์ˆ˜ ์„ ์–ธ์‹๋„ ํ˜ธ์ด์ŠคํŒ…์˜ ๋Œ€์ƒ์ด๋ฉฐ ํ•จ์ˆ˜ ์ „์ฒด๊ฐ€ ํ˜ธ์ด์ŠคํŒ…์ด ๋ฉ๋‹ˆ๋‹ค.

console.log(myFunction()); // "Hello, World!"
function myFunction() {
    return "Hello, World!";
}

ํ•จ์ˆ˜ ํ‘œํ˜„์‹๊ณผ ํ˜ธ์ด์ŠคํŒ…

ํ•จ์ˆ˜ ํ‘œํ˜„์‹์€ ๋ณ€์ˆ˜์— ํ• ๋‹น๋œ ํ•จ์ˆ˜๋ฅผ ์˜๋ฏธํ•˜๋ฉฐ, ๋ณ€์ˆ˜ ์„ ์–ธ๋งŒ ํ˜ธ์ด์ŠคํŒ…์ด ๋˜๊ณ  ํ•จ์ˆ˜๋Š” ํ˜ธ์ด์ŠคํŒ…์ด ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ฆ‰, ํ•จ์ˆ˜ ํ‘œํ˜„์‹์€ ์„ ์–ธ ์ „์— ํ˜ธ์ถœํ•˜๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

console.log(myFunctionExpression()); // TypeError: myFunctionExpression is not a function
var myFunctionExpression = function() {
    return "Hello, World!";
};

์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์ด์œ ์™€ ํ˜ธ์ด์ŠคํŒ…์˜ ๊ณผ์ •์€ ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

myFunctionExpression;
console.log(myFunctionExpression()); // TypeError: myFunctionExpression is not a function
myFunctionExpression = function() {
    return "Hello, World!";
};

ํด๋ž˜์Šค์™€ ํ˜ธ์ด์ŠคํŒ…

ํด๋ž˜์Šค์˜ ์„ ์–ธ๋„ ํ˜ธ์ด์ŠคํŒ…์˜ ๋Œ€์ƒ์ด์ง€๋งŒ, let๊ณผ const์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํ˜ธ์ด์ŠคํŒ…์ด ์ผ์–ด๋‚˜๋„ 'TDZ'์— ๋“ค์–ด๊ฐ€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ ํด๋ž˜์Šค ์„ ์–ธ ์ด์ „์— ํ•ด๋‹น ํด๋ž˜์Šค๋ฅผ ์ฐธ์กฐํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์ฐธ์กฐ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

const toy = new Toy(); // ReferenceError: Cannot access 'Toy' before initialization
class Toy {}

๐Ÿ“• ๋งˆ๋ฌด๋ฆฌ

ํ˜ธ์ด์ŠคํŒ…์„ ์ดํ•ดํ•˜๋ฉด ์ฝ”๋“œ๋ฅผ ๋ณด๋‹ค ํšจ๊ณผ์ ์œผ๋กœ ์ž‘์„ฑํ•˜๊ณ  ๋””๋ฒ„๊น…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ฐธ๊ณ  ๋ฌธํ—Œ:

๋ฐ˜์‘ํ˜•
profile

๐Ÿ’ป์šฉ๋‡ฝ ๊ฐœ๋ฐœ ๋…ธํŠธ๐Ÿ’ป

@์šฉ๋‡ฝ

ํฌ์ŠคํŒ…์ด ์ข‹์•˜๋‹ค๋ฉด "์ข‹์•„์š”โค๏ธ" ๋˜๋Š” "๊ตฌ๋…๐Ÿ‘๐Ÿป" ํ•ด์ฃผ์„ธ์š”!