Notice
Recent Posts
Recent Comments
Link
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
Archives
Today
Total
관리 메뉴

pgg-dev

[JavaScript] 호이스팅(Hoisting) 본문

JavaScript

[JavaScript] 호이스팅(Hoisting)

pgg-dev 2020. 1. 9. 14:44

호이 스팅이란?

var 를 사용하여 정의된 변수 및 함수의 선언문이 각각 속한 스코프의 꼭대기로 끌어올려지는 작업을 뜻한다. 

var a = 1;

위의 코드는 한 줄의 코드지만 자바스크립트 엔진은 아래와 같이 해석한다.

1
2
var a;
= 1;

1행  변수의 선언문으로써, 컴파일러 단계에서 처리한다.

2행  실행단계에서 처리한다.

스코프의 모든 선언문은 실행 전에 먼저 처리된다.

 

1
2
3
4
for (var i = 0; i < 5; i++) {
  //..
}
console.log(i); //5

일반적으로 변수는 블록 스코프 { } 안에서 유효하기 때문에 블록이 종료된 시점에서 console.log 를 호출하면 출력되지 않는다고 생각한다.

하지만 5가 출력된다.

이러한 현상은 var 변수가 호이스팅 되기 때문이다.

 

변수 호이스팅

1
2
3
4
if (true) {
  var text = "HELLO";
}
console.log(text); //HELLO

위의 코드처럼 작성하더라도, 내부적으로 호이스팅 되어 아래처럼 선언과 할당이 일어난다.

 

1
2
3
4
5
var text; //선언
if (true) {
  text = "HELLO"//할당
}
console.log(text); //HELLO

이처럼 호이스팅은 var 를 사용한 변수의 선언문을 최상단으로 끌어올리는 행위이다.

내부적으로 선언과 할당이 분리되었기 때문에 출력이 가능한 것이다.

 

1
2
3
4
5
6
7
8
function showName() {
  console.log("First Name : " + name);
  var name = "Ford";
  console.log("Last Name : " + name);
}
showName();
//First Name : undefined
//Last Name : Ford

호이스팅 된 코드는 다음과 같다.

 

1
2
3
4
5
6
function showName() {
  var name//선언
  console.log("First name : " + name); // First Name : undefined
  name = "Ford"//할당
  console.log("Last Name : " + name); // Last Name : Ford
}

변수가 호이스팅 되어 최상단에 선언되지만 할당되는 위치에 따라 undefined가 출력된다.

( 선언문만 끌어올려지고 다른 대입문이나 실행 로직 부분은 제자리에 위치한다. )

 

var 의 유효 범위

호이스팅 시 선언문은 유효 범위의 최상단으로 올라간다.

var 는 함수 스코프를 사용하기 때문에 함수 블록 function{ } 안에서 유효하다.

 

1
2
3
4
5
6
7
8
9
10
11
12
test(); //HELLO
function test(){
  if(true){
    var text = 'HELLO';
  }
  console.log(text);
}
 
if(true){
  var score = 100;
}
console.log(score); //100

위의 코드는 아래와 같이 호이스팅 된다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var score;
 
test(); //HELLO
function test(){
  var text;
  
  if(true){
    text = 'HELLO';
  }
  console.log(text);
}
 
if(true){
  score = 100;
}
console.log(score); //100

5행 → var 는 함수 스코프이기 때문에 유효한 함수 범위 내부의 최상단에 위치한다.

글로벌 스코프 또한 하나의 함수 스코프처럼 동작하기 때문에 호이스팅이 일어난다.

 

함수 선언문과 함수 표현식의 호이스팅 

  • 함수 선언문
1
2
3
4
5
sayHello(); //Hello
 
function sayHello() {
  console.log("Hello");
}

실제 코드

 

1
2
3
4
5
function sayHello() {
  console.log("Hello");
}
 
sayHello(); //Hello

호이스팅 된 코드

함수 선언도 최상단으로 끌어올려지기 때문에 정상적으로 출력이 된다.

 
  • 함수 표현식
1
2
3
4
5
sayHi(); //TypeError: sayHi is not a function
 
var sayHi = function() {
  console.log("Hi");
};

실제 코드

 

1
2
3
4
5
6
7
var sayHi; //선언
 
sayHi(); //TypeError: sayHi is not a function
 
sayHi = function() { //할당
  console.log("Hi");
};

호이스팅 된 코드

1행 → 처음에 sayHi는 변수로써 호이 스팅 된다.

3행 → 현재는 변수이기 때문에 함수로써 호출하면 에러가 난다.

5행  호출 이후에 함수로써 할당이 되기 때문에 호출과 할당되는 위치를 확인해야 된다.

 

변수와 함수의 우선순위

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
foo();
 
function foo() {
  console.log(1);
}
 
var foo = function() {
  console.log(2);
};
 
function foo() {
  console.log(3);
}
 
foo();

실제 코드

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var foo; //변수 선언
 
function foo() { //함수 선언
  console.log(1);
}
 
function foo() { //함수 선언
  console.log(3);
}
 
foo(); // 3
 
foo = function() { //변수 할당
  console.log(2);
};
 
foo(); // 2

호이스팅 된 코드

위의 코드처럼 변수 선언이 먼저 되고 함수 선언이 된다.

함수 foo 가 중복 선언되었기 때문에 3이 출력되고, 변수 할당 후에 2가 출력된다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var sayHi = "hi";
 
function sayHi() {
  console.log("Hi");
}
 
function sayHello() {
  console.log("Hello");
}
 
var sayHello = "hello";
 
console.log(typeof sayHi);
console.log(typeof sayHello);

실제 코드

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var sayHi; //변수 선언
var sayHello; //변수 선언
function sayHi() { //함수 선언
  console.log("Hi");
}
function sayHello() { //함수 선언
  console.log("Hello");
}
 
sayHi = "hi"//변수 할당
sayHello = "hello"//변수 할당
 
console.log(typeof sayHi); //string
console.log(typeof sayHello); //string

호이스팅 된 코드

이처럼 변수 선언 함수 선언 변수 할당 순서를 가진다.

 


Hoisting 은 자바스크립트 엔진이 갖고 있는 성질이며, Hoisting 을 일부러 할 필요는 없지만, 방지하는 것이 좋다.

왜냐하면 Hoisting 이 발생하는 코드는 이해하기 어렵기 때문에 유지보수도 힘들어진다.

Hoisting 을 방지하기 위해서, 함수의 경우 선언 후에 호출을 하고, var 대신 const, let 을 위주로 사용한다.

 

 

 

[참고]

https://yuddomack.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85Hoisting

http://chanlee.github.io/2013/12/10/javascript-variable-scope-and-hoisting/

https://scotch.io/tutorials/understanding-hoisting-in-javascript

'JavaScript' 카테고리의 다른 글

[ECMAScript6 / ES6] Map , Set  (0) 2020.01.22
[JavaScript] 이벤트 루프(Event Loop)  (0) 2020.01.13
[ECMAScript6 / ES6] Promise  (0) 2020.01.08
[JavaScript] 프로토타입(prototype)  (0) 2020.01.07
[JavaScript] 클로저 (closure)  (0) 2020.01.06
Comments