var
우리가 모두 아는 var 키워드는 아래와 같은 특징을 가지고 있다.
대부분의 프로그래밍 언어들이 블록 레벨 스코프를 사용하고 있지만, var로 선언된 키워드는 함수레벨 스코프를 갖는다.
var name = 'hello'
function t() {
var name = 'hi'
console.log(name) // hi
}
t()
console.log(name) // hello
생략이 가능하기 때문에, 함수가 선언한 환경의 this에 영향을 받는다. 일반적인 웹 환경에서는 window일 것이다.
var name = 'hello'
var name = 'hi'
console.log(name) // hi
호이스팅이란?
스코프 안에 있는 선언들을 모두 스코프의 최상위로 끌어올리는 것
이다. 자바스크립트 인터프리터가 코드를 해석할 때 함수의 선언, 할당, 실행을 모두 나눠서 처리하기 때문이다. 예를 들어보자.
console.log(name) // undefined
var name = 'hello'
이 코드는 참조 에러가 나지 않고, undefined를 리턴한다. 그 이유는 자바스크립트가 호이스팅을 하면서 아래와 같은 방식으로 코드를 해석하기 때문이다.
var name // undefined
console.log(name)
name = 'hello'
let
let은 es6에서 가장 잘 알려진 기능 중 하나다. var랑 비슷한 것 같지만, 사실 몇가지 다른 점이 있다.
블록 수준 스코프를 가지고 있다.
아래의 예를 살펴보자.
{
{
{
var name = 'hello'
}
}
}
console.log(name) // hello
{
{
{
let name2 = 'hi'
}
}
}
console.log(name2) // ReferenceError: name2 is not defined
let과 const는 모두 블록 수준의 스코프를 사용 하고 있다. 따라서 블록 내부에서 선언한 변수는 모두 지역변수로 취급된다. 때문에 블록 내부에서 선언한 변수들을 참고할 수가 없다.
키워드를 생략하면 var처럼 작동하게 된다.
그렇다.
가끔 인터넷을 뒤지다보면, let과 const는 호이스팅 당하지 않는다는 이야기가 있는데, 이는 잘못된 사실이다. 두 키워드 모두 호이스팅 당하기는 마찬가지이다.
이것을 이해하기 위해서는, Temporary Dead Zone에 대해 알아야 한다.
Temporary Dead Zone
name = 'hello' // ReferenceError: Cannot access 'name' before initialization
let name = 'hi'
자. 만약 name이 호이스팅 되지 않았다면, 두 번째 let선언에서 already declared에러가 났었어야 했다. 근데 현실은 초기화 하기전에 엑세스 할 수 없다는 에러를 내뱉었다.
아래 코드는 어떨까?
function sayHello() {
return name
}
let name = 'hi'
console.log(sayHello()) // hi
별탈없이 hi를 내뱉은 것을 볼 수 있다. 그 말인 즉, name이 분명 호이스팅 되었다는 뜻이다.
다른 이야기로 넘어가서, 자바스크립트에서는 총 3단계에 걸쳐서 변수를 생성한다.
var는 선언과 동시에 초기화가 이루어진다. 즉, 선언과 동시에 undefined가 할당된다.
그러나 let과 const는 다르다. 선언만 될뿐, 초기화가 이루어지지 않는다. 바로 이단계에서 TDZ에 들어가게 되는 것이다. 즉, 선언은 되어있지만, 초기화가 되지 않아 이를 위한 자리가 메모리에 준비되어 있지 않은 상태라는 것이다.
const
const에서 구별되는 특징만 몇가지 살펴보자.
let hello
hello = 'hello'
const hi //SyntaxError: Missing initializer in const declaration
hi = 'hi'
아래 코드는 당연히 안된다.
const hello = 'hello'
hello = 'hi' // TypeError: Assignment to constant variable.
그렇다고 이것도 안되는 것은 아니다.
const hello = ['hi']
hello.push('hello')
const hello = 'hello'
var hi = hello
hi = 'hi'
console.log(hello) // hello
console.log(hi) // hi
객체 자체를 동결시키기 위해서는 Object.freeze를 사용하면 된다.
결론