let, const, var의 차이점과 호이스팅

김형민·2021년 5월 30일
0

호이스팅이란?

함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위의 최상단에 선언하는 것을 말한다.

  • 자바스크립트 함수는 실행되기 전에 함수 안에 필요한 변수값들을 모두 모아서 유효 범위의 최상단에 선언한다.
  • 자바스크립트 Parser가 함수 실행 전 해당 함수를 한 번 훑는다.
    함수 안에 존재하는 변수/함수선언에 대한 정보를 기억하고 있다가 실행시킨다.
    유효 범위: 함수 블록 {} 안에서 유효
    즉, 함수 내에서 아래쪽에 존재하는 내용 중 필요한 값들을 끌어올리는 것이다.
  • 실제로 코드가 끌어올려지는 건 아니며, 자바스크립트 Parser 내부적으로 끌어올려서 처리하는 것이다.
    실제 메모리에서는 변화가 없다.

변수 선언과 할당 중 선언부만 호이스팅한다는 내용을 코드로 확인해보자

noDefine();

function noDefine() {
  // 변수 선언 및 할당 이전에 호출 테스트
  console.log("not defined : " + name);
  var name = "ojava";
  // 변수 초기화 이후 값 확인
  console.log("defined : " + name);
}
 

위 코드의 결과를 예상해보면 첫번째 콘솔 로그에서 사용된 name은 선언되지 않았기 때문에 오류가 발생할 것 같지만, 오류 없이 아래와 같은 로그가 찍힌다.

not defined : undefined
defined : ojava

단, 이 경우 변수 선언하는 var를 생략하는 경우 예상치 않은 결과를 내뱉으므로 주의해야 한다.

noDefine 이라는 함수 범위의 변수를 생성하려했으나, name = "ojava"의 형태로 선언한 경우 이상한 결과가 반환된다.

noDefine();

function noDefine() {
  console.log("not defined : " + name);
  // var name = "ojava";
  name = "ojava"; // 변수 선언 명령어 없이 name 변수에 할당함
  console.log("defined : " + name);
}
not defined : ojava
defined : ojava

오류가 발생하지 않았을뿐 아니라, 변수를 할당하기 전임에도 이미 할당된 값으로 반환해버린다.

함수 내에서 변수 선언 명령어를 제외하고 선언 시 전역 변수의 형태로 사용됨에 주의하자!

이 경우는 함수에서 선언 명령어 없이 초기화 한 값을 전역 변수로 사용하고 있음을 볼 수 있으며, 예상하지 못한 결과값을 반환할 수 있으므로 주의해야 한다.

  • 자바스크립트는 ES6에서 도입된 let, const를 포함하여 모든 선언(var, let, const, function, function*, class)을 호이스팅한다.
  • 이는 let 로 선언된 변수는 스코프의 시작에서 변수의 선언까지 일시적 사각지대(Temporal Dead Zone; TDZ)에 빠지기 때문이다.

하지만, var 로 선언된 변수와는 달리 let 로 선언된 변수를 선언문 이전에 참조하면 참조 에러(ReferenceError)가 발생한다.

이제 var, let, const를 비교해보자!

우선, var는 변수 선언 방식에 있어서 큰 단점을 가지고 있다.

    var name = 'bathingape'
    console.log(name) // bathingape

    var name = 'javascript'
    console.log(name) // javascript

변수를 한 번 더 선언했음에도 불구하고, 에러가 나오지 않고 각기 다른 값이 출력되는 것을 볼 수 있다.

그래서 ES6 이후, 이를 보완하기 위해 추가 된 변수 선언 방식이 let 과 const 이다.

위의 코드 선언을 let으로 바꾸면 에러가 뜬다!
const도 마찬가지로 재선언 해주면 에러가뜬다!

let name = 'bathingape'
    console.log(name) // bathingape

    let name = 'javascript'
    console.log(name) 
    // Uncaught SyntaxError: Identifier 'name' has already been declared

그렇다면 let과 const의 차이점은 무엇일까?

let 은 변수에 재할당이 가능하다. 그렇지만,

let name = 'bathingape'
console.log(name) // bathingape

let name = 'javascript'
console.log(name) 
// Uncaught SyntaxError: Identifier 'name' has already been declared

name = 'react'
console.log(name) //react

const는 변수 재선언, 변수 재할당 모두 불가능하다.

const name = 'bathingape'
console.log(name) // bathingape

const name = 'javascript'
console.log(name) 
// Uncaught SyntaxError: Identifier 'name' has already been declared

name = 'react'
console.log(name) 
//Uncaught TypeError: Assignment to constant variable.

그렇다면 어떤 선언방식이 좋을까?

무엇이 좋다고 확실하게 말하기 어려우나 상황에따라 좋은 방법은 있는 것 같다!

변수 선언에는 기본적으로 const를 사용하고, 재할당이 필요한 경우에 한정해 let 을 사용하는 것이 좋다.

그리고 객체를 재할당하는 경우는 생각보다 흔하지 않다. const 를 사용하면 의도치 않은 재할당을 방지해 주기 때문에 보다 안전하다.

재할당이 필요한 경우에 한정해 let 을 사용한다. 이때, 변수의 스코프는 최대한 좁게 만든다.

재할당이 필요 없는 상수와 객체에는 const 를 사용한다.

profile
항해 중인 개발자

0개의 댓글