ES5와 ES6가 혼재된 자바스크립트 소스를 명확하게 읽고 적용하기 위해 정리해 둡니다.
ECMA는 정보통신에 대한 표준을 제정하는 기구로 다음과 같이 자바스크립트에 대한 표준을 정의하였습니다.
ECMAScript
자바스크립트는 이러한 표준을 준수하는지에 따라 버전을 나누고 있습니다.
ECMA-262 표준의 버전 6이며 짧게 'ES6', 'ES2015', 'ECMAScript 2015', 라고도 합니다. 보통 자바스크립트는 ES5와 ES6기준으로 문법과 표현에서 많은 개선이 일어났습니다.
IE와 같은 낡은 브라우저는 ES6를 준수하지 못합니다. 따라서 바벨을 통해 이러한 호환성을 줄이고자 ES6의 코드를 ES5의 코드로 바꿔주게 됩니다.
var a = 5;
var b = 10;
if (a === 5) {
let a = 4; // a는 if 블록 내에서만 유효
var b = 1; // b는 현재 사용되고 있는 함수내에서 유효
console.log(a); // 4
console.log(b); // 1
}
console.log(a); // 5
console.log(b); // 1
// ES5
var React = require('react');
var Router = require('react-router');
// ES6
import React from 'react';
import {Route, DefaultRoute, NotFoundRoute} from 'react-router';
ES6에서만 지원되는 클래스
// ES5
function Box(length, width) {
this.length = length;
this.width = width;
}
Box.prototype.calculateArea = function() {
return this.length * this.width;
}
var box = new Box(2, 2);
box.calculateArea(); // 4
// ES6
class Box {
constructor(length, width) {
this.length = length;
this.width = width;
}
calculateArea() {
return this.length * this.width;
}
}
let box = new Box(2, 2);
box.calculateArea(); // 4
// ES6
[1, 2, 3].map(n => n * 2); // [2, 4, 6]
// ES5
[1, 2, 3].map(function(n) { return n * 2; }); // [2, 4, 6]
화살표 표기법(=>
)을 지원하여 표현식을 구성할 수 있습니다. 화살표 표현식의 결과가 반환되며 다른 언어의 람다식 표기법과 유사합니다.
화살표 표현은 표현식의 결과를 반환 하는데 블록 본문의 경우 return을 명시해야 합니다.
var evens = [2, 4, 6, 8,];
// Expression bodies (표현식의 결과가 반환됨)
var odds = evens.map(v => v + 1); // [3, 5, 7, 9]
var nums = evens.map((v, i) => v + i); // [2, 5, 8, 11]
var pairs = evens.map(v => ({even: v, odd: v + 1})); // [{even: 2, odd: 3}, ...]
// Statement bodies (블럭 내부를 실행만 함. 반환을 위해선 return을 명시)
nums.forEach(v => {
if (v % 5 === 0)
fives.push(v);
});
ES6에서 클래스를 정의하는 한가지 방법으로 익명(unnamed)혹은 이름있는(named) 형식으로 정의할 수 있습니다.
var MyClass = class [className] [extends] {
// class body
};
먼저 이름이 없는 표현식을 살펴봅시다.
var Rectangle = class {
constructor(height, width) {
this.height = height;
this.width = width;
}
area() {
return this.height * this.width;
}
}
console.log(new Rectangle(5,8).area());
// expected output: 40
이름을 사용할 경우에는 현재 클래스를 참조할 때 사용할 수 있습니다.
var Foo = class NamedFoo {
constructor() {}
whoIsThere() {
return NamedFoo.name;
}
}
var bar = new Foo();
bar.whoIsThere(); // "NamedFoo"
NamedFoo.name; // ReferenceError: NamedFoo가 정의되지 않음
Foo.name; // "NamedFoo"
클래스 선언문의 경우 반드시 이름이 있어야 합니다.
class Polygon {
constructor(height, width) {
this.area = height * width;
}
}
console.log(new Polygon(4,3).area);
// expected output: 12
클래스 본문은 엄격 모드에서 실행되며 생성자 속성은 선택 사항입니다. 클래스 선언은 함수 선언과 달리 호이스팅의 대상이 아닙니다.
Note:엄격 모드(Strict Mode)
엄격모드는 기존에 무시되던 에러들을 발생시키거나 실수를 바로잡는데 도움이 됩니다. 그리고 향후 버전의 정의되는 문법을 금지합니다. 스크립트 작성 전 'use strict';를 삽입합니다.
super()의 경우에는 생성자 내에서 this키워드 사용전에만 사용할 수 있습니다.
class Polygon {
constructor(height, width) {
this.name = 'Polygon';
this.height = height;
this.width = width;
}
}
class Square extends Polygon {
constructor(length) {
super(length, length);
this.name = 'Square';
}
}
class SkinnedMesh extends THREE.Mesh {
constructor(geometry, materials) {
super(geometry, materials);
this.idMatrix = SkinnedMesh.defaultMatrix();
this.bones = [];
this.boneMatrices = [];
//...
}
update(camera) {
//...
super.update();
}
get boneCount() {
return this.bones.length;
}
set matrixType(matrixType) {
this.idMatrix = SkinnedMesh[matrixType]();
}
static defaultMatrix() {
return new THREE.Matrix4();
}
}
여기서 사용된 get은 객체의 프로퍼티를 가져오는 게터(getter)입니다. 다음과 같은 문법을 가질 수 있습니다.
{get prop() { ... } }
{get [expression]() { ... } }
게터를 사용할 때는 매개변수(parameter)가 없어야 합니다.
표현식을 사용하는 경우 동적으로 이름을 정의할 수 있습니다.
var expr = "foo";
var obj = {
get [expr]() { return "bar"; }
};
console.log(obj.foo); // "bar"
게터는 프로퍼티에 접근하기 전까지 값을 계산하지 않습니다. 접근하지 않는다면 CPU의 자원을 낭비하지 않아 유용합니다.
만일, 한번 접근되 계산되면 이후 접근할 때는 캐시에 두고 다시 계산하지 않습니다.
객체의 프로퍼티를 설정합니다. 문법은 다음과 같습니다.
{set prop(val) { . . . }}
{set [expression](val) { . . . }}
하나의 매개변수인 val을 통해서 값을 설정하게 됩니다.
템플릿 리터럴로도 불리며 여러 조합으로 문자열을 쉽게 생성할 수 있습니다.
// Basic literal string creation
`In JavaScript '\n' is a line-feed.`
// Multiline strings
`In JavaScript this is
not legal.`
// String interpolation
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`
// Construct an HTTP request prefix is used to interpret the replacements and construction
POST`http://foo.org/bar?a=${a}&b=${b}
Content-Type: application/json
X-Credentials: ${credentials}
{ "foo": ${foo},
"bar": ${bar}}`(myOnReadyStateChangeHandler);
배열이나 객체의 요소를 분해하여 필요한 형태로 저장할 수 있습니다.
// list matching
var [a, , b] = [1,2,3];
// object matching
var { op: a, lhs: { op: b }, rhs: c }
= getASTNode()
// object matching 단축 표기
// binds `op`, `lhs` and `rhs` in scope
var {op, lhs, rhs} = getASTNode()
// parameter에서도 사용 가능
function g({name: x}) {
console.log(x);
}
g({name: 5})
// Fail-soft destructuring
var [a] = [];
a === undefined;
// Fail-soft destructuring with defaults
var [a = 1] = [];
a === 1;
function f(x, y = 12) {
return x + y;
}
f(3) // 15
function f(x, ...y) {
// y is an Array ["hello", true]
return x * y.length;
}
f(3, "hello", true) // 6
함수 호출 시 배열을 일련의 인자에 나누어 주입시켜 줍니다.
function f(x, y, z) {
return x + y + z;
}
// Pass each elem of array as argument
f(...[1,2,3]) // 6
가장 기본적으로는 foreach()
를 사용할 수 있습니다. foreach
구문의 인자로 callback 함수를 등록할 수 있고, 배열의 각 요소들이 반복될 때 이 callback 함수가 호출됩니다. callback 함수에서 배열 요소의 인덱스와 값에 접근할 수 있습니다.
var items = ["item1", "item2", "item3"];
items.forEach(function(item) {
console.log(item);
});
// Console
// item1
// item2
// item3
모든 객체에 사용할 수 있으며 객체 키 값을 사용해 요소를 접근합니다. 열거형 속성들에 대해서만 반복 처리합니다.
var obj = {
a: 1,
b: 2,
c: 3
};
for (var prop in obj) {
console.log(prop, obj[prop]); // a 1, b 2, c 3
}
ES6에 추가된 새로운 컬렉션 전용 반복 구문입니다. for of
구문을 사용하기 위해선 컬렉션 객체가 [Symbol.iterator]
속성을 가지고 있어야만 합니다.
var iterable = [10, 20, 30];
for (var value of iterable) {
console.log(value); // 10, 20, 30
}
언어 차원에서 컴포넌트 정의를 위한 모듈을 지원합니다. 런타임 동작은 호스트에 정의된 기본 로더에 의해 정의됩니다. 모듈들이 정상적으로 로드되기 전까지 코드가 실행되지 않습니다.
// lib/math.js
export function sum(x, y) {
return x + y;
}
export var pi = 3.141593;
// app.js
import * as math from "lib/math";
console.log("2π = " + math.sum(math.pi, math.pi)); // 2π = 6.283186
// otherApp.js
import {sum, pi} from "lib/math";
console.log("2π = " + sum(pi, pi)); // 2π = 6.283186
export default
와 export *
문법도 제공합니다.
// lib/mathplusplus.js
export * from "lib/math";
export var e = 2.71828182846;
export default function(x) {
return Math.log(x);
}
// app.js
import ln, {pi, e} from "lib/mathplusplus";
console.log("2π = " + ln(e)*pi*2);
"어떤 것을 완전히 알려거든 그것을 다른 이에게 가르쳐라."
- Tryon Edwards -