[JavaScript] ES6 문법 정리
[JavaScript] ES6 문법 정리
ECMAScript 6
ECMAScript 2015로도 알려져 있는 ECMAScript 6는 ECMAScript 표준의 가장 최신 버전입니다. ES6는 새로운 언어 기능이 포함된 주요 업데이트이며, 2009년도에 표준화된 ES5 이후로 언어 기능에 대한 첫 업데이트이기도 합니다. 현재 주요 JavaScript 엔진들에서 ES6 기능들을 구현 중에 있습니다.
ES6 문법 기능분류
- arrows
- classes
- enhanced object literals
- template strings
- destructuring
- default + rest + spread
- let + const
- iterators + for..of
- generators
- unicode
- modules
- module loaders
- map + set + weakmap + weakset
- proxies
- symbols
- subclassable built-ins
- promises
- math + number + string + array + object APIs
- binary and octal literals
- reflect api
- tail calls
각 기능 설명
Arrow
Arrows(화살표) 함수는 => 문법을 사용하는 축약형 함수입니다. C#, Java 8, CoffeeScript의 해당 기능과 문법적으로 유사합니다. Arrows는 표현식의 결과 값을 반환하는 표현식 본문(expression bodies)뿐만 아니라 상태 블럭 본문(statement block bodies)도 지원합니다. 하지만 일반 함수의 자신을 호출하는 객체를 가리키는 dynamic this와 달리 arrows 함수는 코드의 상위 스코프(lexical scope)를 가리키는 lexical this를 가집니다.
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);
}); // Lexical this // 출력결과 : Bob knows John, Brian
var bob = { _name: "Bob", _friends: ["John, Brian"], printFriends() { this._friends.forEach(f => console.log(this._name + " knows " + f)); } }
Classes
ES6 클래스는 프로토타입 기반 객체지향 패턴을 더 쉽게 사용할 수 있는 대체재입니다. 클래스 패턴 생성을 더 쉽고 단순하게 생성할 수 있어서 사용하기도 편하고 상호운용성도 증가됩니다.
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();
}
}
Enhanced Object Literals
ES6에서 객체 리터럴은 선언문에서 프로토타입 설정, foo: foo 선언을 위한 단축 표기법, 메서드 정의, super 클래스 호출 및 동적 속성명을 지원하도록 향상 되었습니다. 그에 따라 객체 리터럴 및 클래스 선언이 더 밀접되어져, 객체기반 설계가 더 편리해졌습니다.
var obj = { // __proto__
__proto__: theProtoObj, // ‘handler: handler’의 단축 표기
handler, // Methods
toString() { // Super calls
return "d " + super.toString();
}, // Computed (dynamic) property names
[ 'prop_' + (() => 42)() ]: 42
};
Template Strings
Template Strings(ES6 부터는 Template literals라 부름)는 문법적으로 더 편하게 string을 생성할 수 있게 합니다. 이는 Perl, Python 등의 문자열 보간(string interpolation)과 유사합니다. Tagged template literals는 인젝션 공격 방어 혹은 문자열로 부터 상위 데이터 구조체 재조립 등을 위해 string 생성을 커스터마이징이 가능하게끔 해줍니다.
// 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}?`
Destructuring
Destructuring는 배열과 객체에 패턴 매칭을 통한 데이터 바인딩을 제공합니다. Destructuring는 할당 실패에 유연하며, 실패 시 undefined 값이 자동할당 됩니다. 또한 foo[“bar”]와 같이 객체의 속성 값도 자동으로 검색하여 바인딩해줍니다.
// 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;
Default + Rest + Spread
파라미터에 기본 값을 설정할 수 있습니다.
function f(x, y=12) {
// y is 12 if not passed (or passed as undefined) return x + y;
}
f(3) // 15
Let + Const
블록 유효 범위를 갖는 새로운 변수 선언 방법을 지원합니다. let은 var와 유사하게 동작합니다. const는 재할당 및 재선언이 불가능합니다.
function f() {
{
let x;
{ // okay, block scoped name
const x = "sneaky"; // error,
const x = "foo";
} // error, already declared in block
let x = "inner";
}
}
Iterators + For..Of
Iterator 객체는 CLR의 IEnumerable 혹은 Java의 Iterable처럼 사용자 정의의 반복을 가능하게 해줍니다. for..of 반복문이 ES6에서 추가 되었으며 for..in 반복문과 달리 iterator 기반의 컬렉션 전용 반복문입니다. for in 반복문과의 차이점은 for in vs for of를 참고하세요.
let fibonacci = {
[Symbol.iterator]() {
let pre = 0,
cur = 1;
return {
next() {
[pre, cur] = [cur, pre + cur];
return {
done: false,
value: cur
}
}
}
}
}
for (var n of fibonacci) { // truncate the sequence at 1000
if (n > 1000) break;
console.log(n); // 1, 2, 3, 5, 8, ...987
}
Map + Set + WeakMap + WeakSet
일반 알고리즘을 위한 효율적인 데이터 구조를 제공합니다. WeakMap과 WeakSet는 메모리 누수로 부터 자유롭게 해줍니다. 이들 내 저장된 객체에 다른 참조가 없는 경우, garbage collection 될 수 있습니다.
// Sets
var s = new Set();
s.add("hello").add("goodbye").add("hello");
s.size === 2; s.has("hello") === true;
// Maps
var m = new Map();
m.set("hello", 42);
m.set(s, 34);
m.get(s) == 34;
// Weak Maps
var wm = new WeakMap();
wm.set(s, { extra: 42 });
wm.size // undefined (사용된 곳이 없기 때문)
// Weak Sets
var ws = new WeakSet();
ws.add({ data: 42 });
wm.size // undefined (사용된 곳이 없기 때문)
Promises
Promise는 비동기 프로그래밍을 위한 라이브러리입니다. Promise는 미래에 생성되는 값을 나타내는 일급 객체입니다. Promise는 현존하는 많은 JavaScript 라이브러리에 사용되고 있습니다.
function timeout(duration = 0) {
return new Promise((resolve, reject) => {
setTimeout(resolve, duration);
})
}
var p = timeout(1000).then(() => {
return timeout(2000);
}).then(() => {
throw new Error("hmm");
}).catch(err => {
return Promise.all([timeout(100), timeout(200)]);
})
중요한 부분에 대해서 정리를 해두었고, 나머지에 대해서는 추후에 기록하겠습니다.
- generators
- unicode
- modules
-
module loaders
-
proxies
- symbols
- subclassable built-ins
- math + number + string + array + object APIs
- binary and octal literals
- reflect api
- tail calls