ECMAScipt6
우리가 흔히 알고 있는 것은 es5 이다.
그러나 es6로 업데이트를 하게 되면서 추가되는 것들이 많다. 이를 공부해보자
ES5에서 변수를 선언할 수 있는 유일한 방법은 var
키워드를 사용하는 것이었다. var
키워드로 선언된 변수는 아래와 같은 특징을 갖는다. 이는 다른 C-family
언어와는 차별되는 특징(설계상 오류)으로 주의를 기울이지 않으면 심각한 문제를 발생시킨다.
문제점
- Function-level scope
- 전역 변수의 남발
- for loop 초기화식에서 사용한 변수를 for loop 외부 또는 전역에서 참조할 수 있다.
- var 키워드 생략 허용
- 의도하지 않은 변수의 전역화
- 중복 선언 허용
- 의도하지 않은 변수값 변경
- 변수 호이스팅
- 변수를 선언하기 전에 참조가 가능하다.
ES6는 이러한 var의 단점을 보완하기 위해 let과 const 키워드를 도입하였다.
1. let
1.1 Block-level scope
/ | 설명 |
---|---|
Function-level scope | 함수내에서 선언된 변수는 함수 내에서만 유효하며 함수 외부에서는 참조할 수 없다. 즉, 함수 내부에서 선언한 변수는 지역 변수이며 함수 외부에서 선언한 변수는 모두 전역 변수이다. |
Block-level scope | 코드 블럭 내에서 선언된 변수는 코드 블럭 내에서만 유효하며 코드 블럭 외부에서는 참조할 수 없다. |
console.log(foo); // undefined
var foo = 123;
console.log(foo); // 123
{
var foo = 456;
}
console.log(foo); // 456
위에서 처럼 var
는 전역변수로 선언이 된다.
let foo = 123;
{
let foo = 456;
let bar = 456;
}
console.log(foo); // 123
console.log(bar); // ReferenceError: bar is not defined
이처럼 let
을 사용해서 선언을 하게 되면 해당 scope
내에서만 사용이 가능하다.
1.2 중복 선언 안됨
var
는 중복 선언이 가능하였으나 let
은 중복 선언 시 SyntaxError 가 발생한다.
1.3 호이스팅(Hoisting)
호이스팅을 쉽게 말하면 선언문(var, let, function)들을 선두로 옮기는 것이다.
하지만 var
키워드로 선언된 변수와는 달리 let
키워드로 선언된 변수를 선언문 이전에 참조하면 ReferenceError
가 발생한다. 이는 let 키워드로 선언된 변수는 스코프의 시작에서 변수의 선언까지 일시적 사각지대(Temporal Dead Zone; TDZ)
에 빠지기 때문이다.
var
키워드로 선언된 변수는 선언 단계와 초기화 단계가 한번에 이루어진다. 즉,스코프에 변수가 등록(선언단계)되고 변수는 undefined
로 초기화(초기화단계)된다. 따라서 변수 선언문 이전에 변수에 접근하여도 Variable Object
에 변수가 존재하기 때문에 에러가 발생하지 않는다. 다만 undefined
를 반환한다.
이러한 현상을 변수 호이스팅(Variable Hoisting)이라한다.
이후 변수 할당문에 도달하면 비로서 값의 할당이 이루어진다.
let 키워드로 선언된 변수는 선언 단계와 초기화 단계가 분리되어 진행된다.
즉, 스코프에 변수가 등록(선언단계)되지만 초기화 단계는 변수 선언문에 도달했을 때 이루어진다. 초기화 이전에 변수에 접근하려고 하면 ReferenceError 에러가 발생한다.
이는 변수가 아직 초기화되지 않았기 때문인데 스코프의 시작 지점부터 초기화 시작 지점까지를 일시적 사각지대(Temporal Dead Zone; TDZ)라고 부른다.
2018-01-08 추가
2. const
우리가 흔히 말하는 상수(변하지 않는 값)
라고 부르는 것이다. 하지만 반드시 상수만을 위해 사용하지는 않는다. 또한 let
과 대부분 동일한 특징을 가진다.
2.1 선언과 초기화
let은 초기화 이후 다른 값으로 재할당이 자유로우나 const는 초기화 이후 재할당이 금지 된다.
const SSEON = 123;
SSEON = 456; // TypeError: Assignment to constant variable.
- 위와 같이 타입에러가 뜨게 된다.
- 선언과 동시에 초기화를 안하게 되면 Syntax에러가 나오게 된다.
const sseon; // SyntaxError: Missing initializer in const declaration
- const는 let과 마찬가지로 Block-level scope 를 갖는다.
{
const SSEON = 10;
console.log(SSEON); //10
}
console.log(SSEON); // ReferenceError: SSEON is not defined
2.2 상수
상수는 가독성의 향상과 유지보수의 편의를 위해 적극적으로 사용 해야 한다.
네이밍이 적절한 상수로 선언하면 가독성과 유지보수성이 대폭 향상된다.
- const는 객체에도 사용할 수 있으나, 재할당을 역시 안된다. 그러나 const 객체에 프로퍼티 추가는 가능 하다.
const obj = { sseon: 10};
obj.age = 12;
obj; // {sseon: 10, age: 12}
obj = { atef : 10 }; // TypeError: Assignment to constant variable.
- 여기서 재할당이 안된다는 것은 const 변수의 값이 객체인 경우, 객체에 대한 참조의 변경 을 금지한다는 것을 의미한다.
객체 타입 변수 선언에는 const를 사용하는 것이 좋은 이유
- 객체에 대한 참조는 변경될 필요가 없다. 즉, 재할당이 필요없다. 만일 새로운 객체에 대한 참조를 변수에 할당해야 한다면 새로운 변수를 사용하면 된다.
- const를 사용한다 하더라도 객체의 프로퍼티를 변경할 수 있다.
3. var vs. let vs. const
ES6를 적용하게 되면서 var
를 사용하기 보다는 용도에 따라 let
과 const
를 사용하는 것이 좋다고 한다.
- 변경이 발생하지 않는(재할당이 필요없는) primitive형 변수와 객체형 변수에는 const를 사용한다.
- 재할당이 필요한 primitive형 변수에는 let를 사용한다.