JS : Hoisting과 var, let, const

eunsonny·2020년 8월 17일
0

What I've learned

목록 보기
11/28

Hoisting (호이스팅)

우리는 앞서 JavaScript의 변수 선언 방식에 대해서 알아보았다. 그럼 그에 이어 변수 사용에 있어서 꼭 알아두어야 할 호이스팅에 대해서 알아보자!

호이스팅이란 사전적 의미로는 '끌어올린다'는 의미로 변수나 함수의 선언을 스코프의 위로 끌어올린다는 것을 의미한다.

이렇게 들어서는 이해가 잘 되지 않을 수 있다. 구체적인 사례를 보며 호이스팅에 대해서 파악해 보도록 하자

console.log(name) // undefined
var name = ‘seo’

위의 코드를 보면 첫 줄에 name을 출력하는데 에러가 나지 않고 undefined가 나온다. 왜냐면 실행시점에 호이스팅에 의해 var 변수가 아래와 같이 최 상단에 선언되기 때문이다.

var name; // 실행시점에 name 변수가 hoisting 되어 해당 위치로 이동
console.log(name)
name = ‘seo’

우리는 var 가 hoisting 된다는 사실을 확인했다. 그렇다면 let과 const는 어떨까?

let과 const는 호이스팅 되지 않는다고? No!!!!

console.log(name) //ReferenceError: name is not defined
let name = 'seo'

let으로 변수를 선언하면 에러가 발생한다. 여기서 let 키워드로 선언된 변수는 hoisting 되지 않는구나 라고 오해할 수 있지만 그렇지 않다.

var 뿐만 아니라 let과 const 키워드로 선언된 변수들도 호이스팅 된다. 아래 예제를 보자.

var name = ‘seo’ // 전역변수
{
    console.log(name) //  name is not defined
    let name = ‘seo’ / 지역변수
}

최 상단에 name 변수를 선언했는데 왜 console.log는 에러를 출력할까? 그 이유는 {} 블록 내부에 let으로 선언된 name 변수가 호이스팅 되었기 때문이다. let name 변수가 호이스팅 되지 않았다면 console.log의 결과는 전역변수가 가리키는 seo가 출력되어야한다.

그렇다면 여기서 한 가지 의문이 들 수 있다. 좋아, let 으로 선언된 변수도 호이스팅 된다고?🤔
그러면 왜 출력결과가 undefined가 아니라 name is not defined 에러가 발생하지?

이를 이해하기 위해서 자바스크립트에서 변수가 어떻게 할당되고 var와 let이 어떤 차이가 있는지 알아야 한다.

변수의 3단계 생성과정
변수는 아래와 같이 3단계의 과정을 통해 생성됩니다.

  • 선언단계 : 변수를 실행컨텍스트의 변수객체에 등록한다.
  • 초기화 단계 : 실행 컨텍스트에 등록 된 변수객체에 대한 메모리를 할당한다. 이 단계에서 변수는 undefined로 초기화 된다.
  • 할당단계 : undefined로 초기화 된 변수에 값을 할당한다.

var 키워드로 변수를 만들 경우, 선언단계와 초기화 단계가 동시에 이뤄진다. 아래 예제를 다시 보도록 하자.

// 스코프의 선두에서 선언 단계와 초기화 단계가 실행된다.
// 따라서 변수 선언문 이전에 변수를 참조할 수 있다.

console.log(foo); // undefined

var foo;
console.log(foo); // undefined

foo = 1; // 할당문에서 할당 단계가 실행된다.
console.log(foo); // 1

위 코드에서 var 로 선언된 변수는 hoisting 되어 선언과 초기화가 동시에 이뤄지기 때문에 undefined로 출력된다.

하지만 let 키워드는 선언단계와 초기화 단계가 분리되어 진행된다.

// 스코프의 선두에서 선언 단계가 실행된다.
// 아직 변수가 초기화(메모리 공간 확보와 undefined로 초기화)되지 않았다.
// 따라서 변수 선언문 이전에 변수를 참조할 수 없다.

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

let foo; // 변수 선언문에서 초기화 단계가 실행된다.
console.log(foo); // undefined

foo = 1; // 할당문에서 할당 단계가 실행된다.
console.log(foo); // 1

let 키워드로 선언된 변수는 hoisting 되어 선언단계가 이뤄지지만 초기화 단계는 실제 let이 사용된 코드에 도착했을 때 이뤄진다. 따라서 초기화 단계 이전에 변수에 접근하려하면 reference 에러가 발생하는 것이다.

그렇다면 const 변수는?

const 변수는 let과 매우 유사하지만 차이점은 const 로 선언되면 값이 상수화되어 변경이 불가능하다. 또한 const 로 선언될 경우 선언과 동시에 초기화를 해야 한다.

var name;
name = 'seo'
const age = 29; // 선언과 동시에 초기화 필요
//const age;    // const 변수를 선언만 할 경우 에러가 발생
//age  = '29';

마지막으로 자바스크립트는 ES6에서 도입된 let, const를 포함하여 모든 선언(var, let, const, function, function*, class)을 호이스팅한다는 사실을 기억해 두자!☺️

*참고자료

profile
코린이 🙆

0개의 댓글