[JS] Hoisting

Minyoung's Conference·2022년 10월 19일
0

JavaScript

목록 보기
26/28
post-thumbnail
호이스팅에 대해 알아보자

console.log(test()) // "test"
console.log(testValue()) // error

// 함수 선언
function test(){
    return "test";
}

//함수 표현식
var testValue = function(){
    return "testValue";
}

일단 어색한 부분이 함수 선언이 아래에가 있고 함수 호출이 위에 있다.
선언되기전에 함수 실행이 작동하는지 확인해보자.

함수 선언방식은 동작하고 함수 표현식은 에러가 뜬다.

함수에는 두 가지 리터럴 형태가 있다. 

1. 함수 선언 (함수 선언은 function 키워드 뒤로 함수의 이름을 적어서 사용)

2. 함수 표현식 (함수 표현식은 function 키워드 뒤로 이름을 적지않고 사용, 익명함수)

함수 선언은 코드를 실행할 때 함수를 포함하는 스코프 최상단으로 끌어올려진다.
(그래서 함수 선언 전에 함수를 실행해도 에러가 발생하지 않는다.)
위처럼, 코드를 작성해도 
function test(){
	return "test";
}
console.log(test());

이렇게 동작한다. 이런 자바스크립트 특성을 호이스팅이라고 한다.

그에 반해, 함수 표현식은 변수를 통해서 함수를 참조하기 때문에 호이스팅이 일어나지 않는다.

왜 표현식은 호이스팅이 일어나지 않을까? 변수가 수상하다!

console.log(testValue); //undefined
console.log(undeclared); //error

var testValue = 100;

선언하지 않은 변수는 당연히 에러가 나고, 선언한 변수도 '값'까지 끌어올려지지는 않는다.
(testValue라는 이름만 끌어올려지기에 undefined가 나온다.)

console.log(testValueVar()); //error

var testValueVar = function testValue(){
   return "hoist Test"; 
}

변수는 함수와 달리 선언만 끌어올려진다는 점에 주의해야한다.

또 다른 예제를 들어보자.

console.log(test); //undefined

var condition = false;

if(condition){
	var test = "this is test";
}

에러가 떠야하지 않은가? condition의 조건이 true일 때 If 조건문이 실행되는 것으로 알지만
실행이 되어 undefined가 나왔다. 

이유는 if문 내의 변수가 전역 스코프이기 때문이다. if문과는 상관이 없다. 
var test는 전역공간에 선언되어 있어서 test 자체만 호이스팅 되었다. 
(값은 undefined, 변수가 있다는 건 안다)

함수안에서 변수의 선언과 초기화가 이루어지는 경우는 어떨까?

console.log(test()); // "hoist test"
console.log(value); // error

function test(){
	var value = "hoist";
	return value + " test"; 
}

test() 함수 선언은 호이스팅이 되어 실행되고, 
value라는 변수는 함수스코프 내에서 최상단으로 가기때문에 전역에서는 알 수없다.
그래서 에러가 뜬다.

변수 선언 역시 코드르 실행할 때 변수를 포함하는 스코프 최상단으로 끌어올려진다.
함수 안에 선언된 변수는 함수 스코프 안에서 최상단으로 끌어올려진다.

**호이스팅이 되지 않는 선언들도 있다**

console.log(test1); // Reference Error cannot access before initialization
console.log(test2); // Reference Error cannot access before initialization
console.log(Tester); // Reference Error cannot access before initialization

let test1 = "let value";
const test2 = "const value";

class Tester{
	constructor(){
		this.name = "test";
	}

}

**블록 스코프를 생성하는 let, const는 호이스팅이 일어나지 않는다. class 또한 마찬가지이다.
var로 선언된 변수는 호이스팅되지만 let, const로 선언된 변수와 상수는 TDZ(Temporal Dead Zone. 임시 접근 불가구역)구역에 배치된다. 이 값들을 선언이 실행된 후에 TDZ에서 제거되어 사용가능한 상태가 된다.** 

[정리]
- 함수 선언과 변수 선언은 코드를 실행할 때 해당 선언 스코프 최상단으로 끌어올려진다.
이런 현상을 호이스팅이라고 한다.
- 선언한 변수의 값은 끌어올려지지 않는다.
- let, const, class 선언은 호이스팅 현상이 일어나지 않는다.

(인프런 "코딩인터뷰를 저격하는 JS 스나이퍼 양성학교" 참고)

profile
안녕하세요, FE 개발자 김민영입니다.

0개의 댓글