자바스크립트 2015는 ECMASCript6 또는 ES6이라고도 하며, 자바스크립트 언어의 새로운 버전입니다. ES6에는 클래스, 모듈, 새로운 변수 선언 키워드와 프로미스를 비롯해 복잡한 애플리케이션을 작성하기 위한 새로운 구문이 많이 추가됐습니다. 또한 화살표 함수, 템플릿 문자열, 분해와 같이 코드의 표현력을 높이기 위한 새로운 도우미와 편의 문법 기능도 추가됐습니다.

클래스

자바스크립트 클래스는 ES6에 추가됐으며 자바스크립트의 기존 프로토타입 기반 상속에 기반을 두는 편의 문법입니다. 클래스 구문이 자바스크립트에 새로운 객체 지향 상속을 추가하는 것은 아니지만 훨씬 간단하고 알아보기 쉬운 자바스크립트 클래스 구문으로 객체를 상속하고 상속을 처리할 수 있습니다.

클래스는 프로토타입 기반 상속, 상위 호출, 인스턴스와 정적 메소드, 생성자를 지원합니다.

class Point {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
    toString() {
        return `(${this.x}, ${this.y})`;
    }
}
class Pixel extends Point {
    constructor(x, y, color) {
        super(x, y);
        this.color = color;
    }
    toString() {
        return super.toString() + ' in ' + this.color;
    }
}

const p = new Pixel(25, 8, 'green');
p.toString();   // (25, 8) in green

내부를 들여다보면 ES6 클래스는 완전히 새로운 것이라기보다 기존의 생성자 함수를 작성하는 좀 더 편리한 구분이라고 할 수 있습니다. typeof로 이를 확인할 수 있습니다.

typeof Point    // 'function'

모듈

모듈은 모든 프로그래밍 언어에서 가장 중요한 기능이며, ES6에서는 일급 시민이 됐습니다. ES6 모듈은 자바스크립트 코드를 포함하는 파일입니다. 특수한 모듈 키워드는 따로 없으며 export 키워드가 추가되지만 일반적인 스크립트와 거의 동일합니다.

익스포트(export)

기본적으로 모듈 안에서 선언된 모든 사항은 해당 모듈에 대해 로컬로 존재합니다. 모듈 안에서 선언한 항목을 공용으로 선언하고 다른 모듈에서 사용할 수 있게 하려면 export 를 이용해 항목을 익스포트해야 합니다.

function generateRandom() {
    return Math.random();
}

function sum(a, b) {
    return a + b;
}

export { generateRandom, sum }

최상위 함수, 클래스, var, let, const를 익스포트할 수 있습니다.

임포트(import)

import문은 외부 모듈, 다른 스크립트 등에서 익스포트한 함수, 객체, 기본형을 불러서 사용하는 데 사용됩니다.

import { generateRandom, sum } from 'utility';

console.log(generateRandom());  // 임의의 수를 로깅합니다.
console.log(sum(1, 2));  // 3

기본 익스포트

기본 익스포트를 사용해 모듈에서 단일 값을 익스포트할 수 있습니다.

var utils = {
    generateRandom: function() {
        return Math.random();
    },
    sum: function(a, b) {
        return a + b;
    }
};

export default utils;

임포트 할 떄는 기본 익스포트의 이름을 지정하면 됩니다.

import utils from 'utility';

console.log(utils.generateRandom());    // 임의의 수를 로깅합니다.
console.log(utils.sum(1, 2));   // 3

let과 const

var 선언은 다음 예제 코드에서 볼 수 있듯이 함수 내에서 로컬 스코프만 갖는 잠재적 위험성을 안고 있습니다.

function foo() {
    var myVariable = '10';
}

foo()
console.log(myVariable) // 변수가 함수 스코프이므로 "undefined" 오류가 발생합니다.

반면에 다른 블록 구조 안에서 선언한 변수는 전역 스코프를 갖습니다.

if (true) {
    var myVariable = "10";
}

console.log(myVariable) // '10'이 출력됩니다. myVariable 변수는 'if' 블록에 속하지 않고 전역 스코프를 갖습니다.

let

ES6에서는 변수를 선언하는 새로운 두 키워드인 let과 const가 추가됐습니다. 두 구조는 모두 블록 스코프를 갖는 바인딩 구조라고 할 수 있으며, let은 개선된 var라고 보면 됩니다.

if (true) {
    let myVariable = "10";
}

console.log(myVariable) // "undefined" 오류가 발생 - 변수가 if 블록 스코프를 갖습니다.

var를 사용할 수 있는 곳에는 let을 사용하는 것이 일반적으로 안전합니다.

const

const 선언은 단일 값 할당을 위한 선언으로서 값에 대한 읽기 전용 참조를 만듭니다. 포함된 값이 변경 불가가 되는 것은 아니며 변수 식별자를 다시 할당할 수 없다는 의미입니다.

const MY_FAV = 7;   // MY_FAV를 상수로 정의하고 값 7을 지정합니다.
MY_FAV = 20;        // "상수에 값 할당" 오류가 발생합니다.

프로미스

프로미스는 비동기 프로그래밍을 위한 라이브러리이며, 미래에 사용 가능할 수 있는 값에 대한 일급 표현입니다. 프로미스는 여러 기존 자바스크립트 라이브러리에 사용되고 있습니다.

function timeout(duration = 0) {
    return new Promise((resolve, reject) => {
        setTimeout(resolve, reject);
    })
}

var p = timeout(1000).then(() => {
    return timeout(2000);
}).then(() => {
    throw new Error("hmm");
}).catch(err => {
    return Promise.all([timeout(100), timeout(200)]);
})

화살표 함수

화살표는 => 구문을 이용하는 함수 단축 표기법입니다. 화살표 함수는 구문을 간결하게 하고 부모 스코프와 렉시컬(lexical) this를 공유하는 두 가지 용도로 사용됩니다.

간결한 구문

기존 자바스크립트 함수 구문은 함수가 문 하나를 포함하느냐 여러 페지이를 포함하느냐와 상관없이 유연성을 제공하지 않습니다. 즉, 함수가 필요할 때마다 귀찮은 function () {} 구문을 모두 타이핑해야 합니다. 화살표 함수의 가장 큰 장점은 간결한 구문을 사용할 수 있다는 것입니다.

// 간단한 예
setInterval(() => console.log("Time is passing"), 1000);

// 한 행 함수(암시적 반환)
let square = (num) => num * num;
console.log(square(5))  // 25를 반환

// 여러 행
num.forEach(v => {
    if (v % 5 === 0)
        fives.push(v);
})

// 여러 행 함수(암시적 반환)
let actors = ['Adam West', 'Michael Keaton', 'Val Kilmer', 'George Clooney', 'Christian Bale', 'Ben Affleck']
actors.map((actor) => (
    actor + ' was Batman!\n'
));

렉시컬 바인딩

자바스크립트의 모든 함수는 자체 this 컨텍스트를 정의하는데, 우회하기는 어렵지 않지만 귀찮은 것이 사실입니다. 화살표 함수는 this의 값을 선언된 위치에서 부모 스코프와 렉시컬 바인딩(또는 정적 바인딩)합니다.

var bob = {
    _name: "Bob",
    _friends: [],
    printFriends() {
        this._friends.forEach(f =>
            console.log(this._name + " knows " + f));
    }
}

템플릿 문자열

자바스크립트의 문자열은 파이썬이나 루비 둥의 다른 언어에 비해 제한적이고 기능도 부족합니다. ES6의 템플릿 문자열은 편의 문법을 활용해 문자열을 구성하는 방법으로 기존 문자열의 한계를 근본적으로 해결했습니다.

구문

템플릿 문자열은 일반 문자열의 작은따옴표나 큰따옴표 대신 백틱(``)을 이용합니다. 예를 들어, 다음과 같이 템플릿 문자열을 작성할 수 있습니다.

var greeting = `Yo World!`;

다음은 일반 문자열보다 복잡한 기능을 하는 예를 확인해보겠습니다.

문자열 대체

템플릿 문자열의 첫 번째 기능은 문자열 대체입니다. 유효한 자바스크립트 식(예: 변수의 합)을 템플릿 리터럴 안에 지정하면 동일한 문자열의 일부로 결과가 출력됩니다.

템플릿 문자열은 다음 예와 같이 ${} 구문으로 문자열 대체를 위한 자리표시자를 포함할 수 있습니다.

// 간단한 문자열 대체
var name = "Brenden";
console.log(`Yo, ${name}!`);    // "Yo, Brenden!"

다중 행 문자열

자바스크립트에서 다중 행 문자열을 지정하려면 다소 엉성한 방법에 의존해야 합니다. 하지만 이는 템플릿 문자열을 이용하면 아주 간단하게 지정할 수 있습니다. 다음 예와 같이 간단하게 문자열 중간에 줄바꿈을 넣으면 됩니다.

console.log(`string text line 1
string text line 2`);

구조분해 할당

구조분해 할당 구문은 배열이나 객체의 데이터를 여러 변수로 추출할 수 있는 자바스크립트 식입니다.

// 배열 비교
var a, b, rest;
[a, b] = [1, 2];
console.log(a)  // 1
console.log(b)  // 2

// 객체 비교
var robotA = { name: "Brenden" };
var robotB = { name: "Flexo" };

var { name: nameA } = robotA;
var { name: nameB } = robotB;

console.log(nameA); // "Brenden"
console.log(nameB); // "Flexo"

// 매개변수 위치에 사용할 수 있음
function g({name: x}) {
    console.log(x);
}
g({name: 5})    // 5