호이스팅

이재윤·2021년 9월 6일
0

JavaScript

목록 보기
6/10
post-thumbnail

💻 호이스팅이란?

변수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징입니다.
❗ 변수 선언뿐만 아니라 var, let, const, function, function*, class 키워드를 사용해서 선언하는 모든 식별자는 호이스팅이 됩니다. 모든 선언문은 런타임(실행) 이전 단계(평가)에서 먼저 실행되기 때문입니다. (실행 컨텍스트 참고)

💻 var 키워드로 선언한 변수의 문제점

  1. 변수 중복 선언 허용
    var 키워드로 선언한 변수는 중복선언이 가능합니다.
var x = 1;
var y = 1;

var x = 100;
var y;

console.log(x); // 100
console.log(y); // 1
  1. 함수 레벨 스코프
    var 키워드로 선언한 변수는 함수 코드 블록만을 스코프로 인정합니다.
    함수 실행문을 만나 함수 평가가 이루어질 때 함수 실행 컨텍스트가 만들어지며, 새로운 Lexical Environment가 생성되기 때문입니다.
var x = 1;
if (true) {
  var x = 10;
}
console.log(x); // 10
  1. 변수 호이스팅
    var 키워드는 호이스팅에 의해 선언문 이전에 참조할 수 있습니다. 단 결과는 undefined가 나오게 됩니다.
    전역 코드 평가과정에서 변수 선언문 foo를 실행 시켜 foo를 Lexical Environment의 환경 레코드에 키로 등록을 하게됩니다. 이때 동시에 초기화를 진행해 undefined가 할당 됩니다.
console.log(foo); // undefined
foo = 123;
console.log(foo); // 124
var foo;

💻 let 키워드

  1. 변수 중복 선언 금지
    let 키워드로 변수를 중복 선언할 경우 에러가 발생하게 됩니다.
var foo = 123;
var foo = 456;

let bar = 123;
let bar = 456; // SyntaxError
  1. 블록 레벨 스코프
    let 키워드로 선언한 변수는 코드 블록을 스코프로 인정하는 블록 레벨 스코프를 따릅니다.
    블록 코드를 실행할 때 새로운 Lexical Environment가 생성되며, 현재 실행 중이던 실행 컨텍스트가 새롭게 만들어진 Lexical Environment를 참조하게 됩니다. (실행 컨텍스트 참고)
let foo = 1;
{
  let foo = 1;
  let bar = 3;
}
console.log(foo); // 1
console.log(bar); // Reference Error
  1. 변수 호이스팅
    var와 마찬가지로 let도 호이스팅이 일어나나 발생하지 않는것 처럼 동작합니다.
    선언과 동시에 undefined로 초기화되는 var와 달리 let은 선언단계와 초기화 단계가 분리되어 진행됩니다. 만약 초기화 단계 이전에 변수에 접근하려 하면 에러가 발생합니다.

    TDZ(Temporal Dead Zone)이란?
    스코프의 시작 지점부터 초기화 시작 지점까지 변수를 참조할 수 없는 구간을 의미합니다.

console.log(foo);
let foo; // 변수 선언문에서 초기화 단계가 진행됩니다.
console.log(foo); // undefined
foo = 1;
console.log(foo);

let foo = 1;
{
  console.log(foo); // Reference Error
  let foo = 2;
}

만약 호이스팅이 발생하지 않았다면, 블록 코드에서 결과는 에러가 아닌 1이여야 합니다.

💻 const 키워드

  1. 선언과 초기화
    const 키워드는 반드시 선언과 동시에 초기화가 일어나야 합니다.
  2. 호이스팅
    let과 마찬가지로 호이스팅이 발생하나, 일어나지 않은 것 처럼 동작합니다.
  3. 재할당 금지
    let과 달리 한번 값을 할당한 변수에 다른 값을 재할당 할 수 없습니다.
    ❗ 객체를 할당할 경우 객체 내부의 값을 바꿀 수 있다
const person = {
  name: 'Lee';
}
person.name = 'Kim';
console.log(person); //{name: 'Kim'}

0개의 댓글