호이스팅

변수나 함수 선언들이 포함된 범위 상단으로 끌어올려지는 동작을 말한다.

이는 코드의 실제 실행 순서와는 다르게 해석되어 변수와 함수의 선언만 끌어올려지고 초기화는 끌어올려지지 않는다는 점에서 의미를 가진다.

 

변수 호이스팅

변수의 선언은 호이스팅 되지만, 변수 초기화는 호이스팅 되지 않는다. 이는 변수 선언이 코드의 최상단으로 이동된 것처럼 동작하지만 초기화는 원래 위치에 남아 있음을 의미한다.

 

실제 코드

console.log(a); // undefined
var a = 10;
console.log(a); // 10

 

자바스크립트 엔진에 의해 해석된 코드

var a;
console.log(a); // undefined
a = 10;
console.log(a); // 10

 

a 변수의 선언만 끌어올려지고 초기화는 원래 위치에 남아있게 된다.

 

let, const 키워드의 경우 선언된 변수는 호이스팅 되지만 var와 달리 초기화 전에 해당 변수에 접근하면 '일시적 사각지대(TDZ, Temporal Dead Zone)'으로 인해서 ReferenceError가 발생한다. 

 

함수 호이스팅

함수 선언은 변수 선언과 다르게, 함수의 정의 전체가 호이스팅 된다. 이는 함수가 코드에서 선언된 위치와 상관없이 호출될 수 있음을 의미한다.

 

작성된 함수 코드

greet(); // "Hello, World!"

function greet() {
  console.log("Hello, World!");
}

 

실행되는 엔진의 해석

function greet() {
  console.log("Hello, World!");
}

greet(); // "Hello, World!"

 

함수 표현식 호이스팅

함수 표현식은 변수 선언과 유사하게 동작하여 함수 선언과는 다르게 함수의 정의가 호이스팅 되지 않는다.

 

함수 표현식 코드

sayHello(); // TypeError: sayHello is not a function

var sayHello = function() {
  console.log("Hello!");
};

 

실행되는 엔진의 해석

var sayHello;

sayHello(); // TypeError: sayHello is not a function

sayHello = function() {
  console.log("Hello!");
};

 

sayHello 변수의 선언만 호이스팅 되어 상단으로 간다. 초기화는 원래 위치에 남아있어 sayHello가 함수로 초기화되기 전에 호출하기 때문에 TypeError가 발생한다.

 

호이스팅 동작 원리

자바스크립트의 실행 콘텍스트가 생성되는 과정에서 발생한다. 

1. 생성 단계 : 변수와 함수 선언이 메모리에 저장되고 변수는 undefined로 초기화된다.

2. 실행 단계 : 코드를 순차적으로 실행하면서 변수에 값이 할당되고, 함수호출이 이루어진다.

 

작성된 코드

console.log(a); // undefined
foo();          // "foo called"
console.log(bar); // undefined
// bar(); // TypeError: bar is not a function

var a = 10;

function foo() {
  console.log("foo called");
}

var bar = function() {
  console.log("bar called");
};

console.log(a);  // 10
foo();           // "foo called"
bar();           // "bar called"

 

실행되는 엔진의 해석

 

var a;
var bar;

function foo() {
  console.log("foo called");
}

console.log(a);  // undefined
foo();           // "foo called"
console.log(bar); // undefined
// bar(); // TypeError: bar is not a function

a = 10;
bar = function() {
  console.log("bar called");
};

console.log(a);  // 10
foo();           // "foo called"
bar();           // "bar called"

 

따라서 의도하지 않은 문제가 발생하는 것을 막기 위해서는 호이스팅이 동작하는 방식에 대한 이해가 반드시 필요하다. 

 

호이스팅으로 인한 문제를 예방하기 위해서 let, const 변수를 사용하는 것이 권장되는 방식이며 var 사용 시 코드의 순서에 유의할 필요가 있다.

728x90
반응형

'Program Language > JavaScript' 카테고리의 다른 글

JavaScript #8 클로저(Closure)  (1) 2024.07.22
JavaScript #7 var 변수에 대해서  (0) 2024.07.22
JavaScript #5 유효 범위, 스코프(Scope)  (0) 2024.07.21
JavaScript #4 변수  (1) 2024.07.21
JavaScript #3 연산자  (1) 2024.07.21

스코프는 변수나 함수가 유효한 범위를 정의한다.

함수 스코프

함수 내부에서 선언된 변수의 유효 범위를 의미한다. 

var 키워드로 선언된 변수는 함수 스코프를 가진다는 의미는 변수가 함수 내 어디서든 접근 가능하지만 함수 외부에서 접근할 수 없음을 의미한다.

 

function Func() {
  var funcScopeVar = "I am inside a function";
  console.log(funcScopeVar); // "I am inside a function"
}

Func();
// console.log(funcScopeVar); // ReferenceError: functionScopedVariable is not defined

 

Func 함수 내에서 선언된 var 변수 funcScopeVar는 함수 내부에서만 접근이 유효하고 함수 외부에서 접근할 때는 ReferenceError가 발생한다.

 

블록 스코프

블록 스코프는 중괄호 {}로 묶인 코드 블록 내부에서 선언된 변수의 유효 범위를 의미한다.

let과 const 키워드로 선언된 변수는 블록 스코프를 가진다. 이는 변수가 블록 내부에서만 접근 가능하며 블록 외부에서는 접근할 수 없음을 의미한다.

 

if (true) {
  let blockScopedVariable = "I am inside a block";
  const anotherBlockScopedVariable = "I am also inside a block";
  console.log(blockScopedVariable);   // "I am inside a block"
  console.log(anotherBlockScopedVariable); // "I am also inside a block"
}

// console.log(blockScopedVariable);   // ReferenceError: blockScopedVariable is not defined
// console.log(anotherBlockScopedVariable); // ReferenceError: anotherBlockScopedVariable is not defined

 

조건문의 중괄호 내에서 선언된 let과 const 변수들은 내부에서만 유효하며 블록 외부인 중괄호 바깥에서 접근 시 ReferenceError가 발생한다.

 

var의 경우 조건문의 중괄호 내에서 선언되어도 외부에서 접근이 유요하다.

if (true) {
  var variable = "I am a var variable";
}

console.log(variable); // "I am a var variable"

 

호이스팅

var, let, const로 선언된 변수는 모두 호이스팅 되지만 let, const로 선언된 변수는 TDZ로 인해 초기화 전에 접근이 불가능하게 된다.

 

 

전역 스코프

변수를 전역 스코프에서 선언할 때 각 키워드의 동작에는 차이가 있다. 

전역 스코프에서 변수의 선언은 코드 전체에서 접근 가능한 범위를 의미하며 변수 선언 방식에 따라 전역 객체에 미치는 영향이 다르게 된다.

 

var

전역 변수로 선언된 var 변수는 전역 객체의 속성이 되며 같은 이름의 변수를 여러 번 선언할 수 있다.

var globalVar = "I am a global var";
console.log(window.globalVar); // "I am a global var"

var globalVar = "I am a redefined global var";
console.log(window.globalVar); // "I am a redefined global var"

 

같은 이름의 변수를 여러 번 선언이 가능하다는 점은 코드가 복잡해질수록 중복된 이름을 사용하여 의도하지 않게 값을 변경하는 등의 문제를 발생시킬 수 있다.

 

또한 전역 객체의 속성이 되기 때문에 전역 네임스페이스 오염을 발생시켜 다른 스크립트나 라이브러리와 충돌할 위험이 있다.

 

var globalVar = "I am global";
console.log(window.globalVar); // "I am global"

 

let, const

let, const로 선언된 전역 변수는 전역 객체의 속성이 되지 않으며 같은 이름의 변수를 같은 스코프에서 두 번 선언할 수 없다.

 

여기서 같은 스코프란 전역 스코프로 다른 함수, 블록 스코프에서는 해당 이름을 사용할 수 있다. 이 경우 해당 스코프 내에서 선언된 변수로만 접근이 가능해지므로 전역에 존재하는 동일한 이름의 다른 변수는 접근할 수 없다.

 

let globalLet = "I am a global let";

function func() {
  let globalLet = "I am a local let";
  console.log(globalLet); // "I am a local let"
}

func();
console.log(globalLet); // "I am a global let"
728x90
반응형

'Program Language > JavaScript' 카테고리의 다른 글

JavaScript #7 var 변수에 대해서  (0) 2024.07.22
JavaScript #6 호이스팅(Hoisting)  (0) 2024.07.21
JavaScript #4 변수  (1) 2024.07.21
JavaScript #3 연산자  (1) 2024.07.21
JavaScript #2 표현식  (0) 2024.07.21

변수

자바스크립트에서 변수를 선언할 때 사용하는 키워드에는 var, let, const가 있다.

각 키워드는 변수의 스코프와 재할당 가능성, 호이스팅 방식에서 차이가 있다.

 

var

함수 스코프

var로 선언된 변수는 함수 스코프를 가지며 함수 내에서 선언된 변수는 함수 전체에서 접근할 수 있다.

 

호이스팅

var로 선언된 변수는 호이스팅 되며 선언이 코드의 최상단으로 끌어올려지고 초기화는 선언한 위치에서 이루어진다.

 

변수 재선언 가능

같은 스코프 내에서 여러 번 선언할 수 있다. 이때 이전 값은 덮어씌워지게 된다.

 

전역 객체에 속성으로 추가

전역 스코프에서 선언된 var변수는 전역 객체의 속성이 된다. (global 또는 window)

 

console.log(x); // undefined (호이스팅)
var x = 5;
console.log(x); // 5

if (true) {
  var y = 10;
}
console.log(y); // 10 (블록 스코프가 아님)

function foo() {
  var z = 20;
  console.log(z); // 20
}
foo();
// console.log(z); // ReferenceError: z is not defined (함수 스코프)

 

let 

블록스코프

let으로 선언된 변수는 블록 스코프를 가지고 블록 내에서만 접근할 수 있다.

 

호이스팅

let으로 선언된 변수는 호이스팅 되지만 선언하기 전에는 사용할 수 없으며 이를 '일시적 사각지대(TDZ, Temporal Dead Zone)'이라고 한다.

 

변수 재선언 불가

같은 스코프 내에서 두 번 선언할 수 없다.

// console.log(a); // ReferenceError: Cannot access 'a' before initialization (TDZ)
let a = 5;
console.log(a); // 5

if (true) {
  let b = 10;
  console.log(b); // 10
}
// console.log(b); // ReferenceError: b is not defined (블록 스코프)

let c = 15;
// let c = 20; // SyntaxError: Identifier 'c' has already been declared (재선언 불가)

 

const

블록스코프

const로 선언된 변수는 블록 스코프를 가진다.

 

호이스팅

const로 선언된 변수는 호이스팅 되지만, 선언하기 전에는 사용할 수 없다. TDZ에 영향을 받는다.

 

변수 재선언 불가

같은 스코프 내에서 두 번 선언할 수 없다.

 

상수

const로 선언된 변수는 초기화 후에 값을 변경할 수 없지만 객체나 배열의 속성은 변경할 수 있다.

 

// console.log(d); // ReferenceError: Cannot access 'd' before initialization (TDZ)
const d = 5;
console.log(d); // 5

if (true) {
  const e = 10;
  console.log(e); // 10
}
// console.log(e); // ReferenceError: e is not defined (블록 스코프)

const f = 15;
// const f = 20; // SyntaxError: Identifier 'f' has already been declared (재선언 불가)

// f = 25; // TypeError: Assignment to constant variable. (값 변경 불가)

const obj = { key: "value" };
obj.key = "new value"; // 객체의 속성은 변경 가능
console.log(obj.key); // "new value"

const arr = [1, 2, 3];
arr.push(4); // 배열의 요소는 추가 가능
console.log(arr); // [1, 2, 3, 4]
728x90
반응형

'Program Language > JavaScript' 카테고리의 다른 글

JavaScript #6 호이스팅(Hoisting)  (0) 2024.07.21
JavaScript #5 유효 범위, 스코프(Scope)  (0) 2024.07.21
JavaScript #3 연산자  (1) 2024.07.21
JavaScript #2 표현식  (0) 2024.07.21
JavaScript #1 개요  (1) 2024.07.21

+ Recent posts