목차
[ES6] Scope 연산자 let, const, arrow function
어떤 순서로 읽을까?
ES6(ECMAScript 2015)는 자바스크립트 언어 표준의 한 판이다. 이 페이지는 관련 글의 목차로 사용한다. 처음이라면 변수의 스코프를 다루는 let/const 글을 읽은 뒤 화살표 함수, 템플릿 리터럴, 클래스로 넘어가면 예제가 이어진다.
flowchart LR 스코프[let / const와 스코프] --> 함수[화살표 함수] 함수 --> 문자열[템플릿 리터럴] 함수 --> 객체[객체와 클래스] 객체 --> 심벌[Symbol]
class는 새로운 객체 상속 모델을 도입한 것이 아니라 프로토타입을 사용하는 문법이다. Symbol은 일반 문자열 키와 충돌하지 않는 키가 필요할 때 살펴보면 된다. 호이스팅과 프로토타입 글은 ES6만의 기능이 아니지만 위 문법의 실행 방식을 이해하는 데 도움이 된다.
같은 프로그램에서 기능이 만나는 지점
ES6라고 부르는 ECMAScript 2015는 문법 하나가 아니라 여러 언어 기능을 함께 도입한 판이다. 다음 예제는 목록에서 활성 사용자를 찾아 화면용 문장을 만든다. 실제 화면에 넣을 때는 출력 위치의 HTML 처리 규칙도 별도로 적용해야 한다.
const users = [
{ id: 1, name: '민수', active: true },
{ id: 2, name: '지연', active: false },
];
const labels = users
.filter(user => user.active)
.map(user => `${user.id}: ${user.name}`);
console.log(labels); // ['1: 민수']
const는 users라는 변수에 다른 배열을 다시 대입하지 못하게 한다. 배열의 내용 자체를 불변으로 만드는 것은 아니다. filter와 map에 전달한 화살표 함수는 간결한 콜백이다. user => user.active처럼 중괄호를 생략하면 표현식의 결과가 반환된다. 백틱으로 감싼 템플릿 리터럴은 ${...} 안의 표현식을 평가해 문자열에 넣는다. 각 기능은 별개지만 데이터 처리 코드에서는 함께 등장한다.
실행 결과가 달라지는 경계
const config = { retries: 2 };
config.retries = 3; // 가능: 객체의 속성 변경
// config = {}; // TypeError: const 변수 재대입
for (let i = 0; i < 2; i += 1) {
setTimeout(() => console.log(i), 0);
}
// 0, 1
let으로 선언한 i는 반복마다 별도의 바인딩을 사용한다. 이전 방식의 var로 바꾸면 같은 변수를 공유해 타이머 콜백이 실행될 때 모두 마지막 값 2를 볼 수 있다. 이는 타이머의 속도 문제가 아니라 스코프 차이다. let과 const는 블록 스코프를 가지며 선언이 처리되기 전에는 접근할 수 없는 구간이 있다. 호이스팅 글에서 이 동작을 더 자세히 본다.
화살표 함수는 주변 this를 사용한다. 따라서 객체의 메서드나 생성자가 필요한 곳에 무조건 바꾸면 동작이 달라질 수 있다. class의 메서드는 보통 여러 인스턴스가 공유하는 프로토타입에 놓인다. 클래스 필드에 화살표 함수를 만들면 인스턴스마다 함수가 생기는 차이도 있다. 위 학습 순서에서 스코프를 먼저 읽고 함수·객체로 넘어가도록 둔 이유다.