pgg-dev
[JavaScript] 호이스팅(Hoisting) 본문
호이 스팅이란?
var 를 사용하여 정의된 변수 및 함수의 선언문이 각각 속한 스코프의 꼭대기로 끌어올려지는 작업을 뜻한다.
var a = 1;
|
위의 코드는 한 줄의 코드지만 자바스크립트 엔진은 아래와 같이 해석한다.
1
2
|
var a;
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 을 위주로 사용한다.
[참고]
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 |