SlideShare a Scribd company logo
ECMAScript 6 Features
2015/06/06
2015/06/30 改訂
taskie
1 / 85
このスライドについて
ECMAScript 6 の新機能を紹介するスライドです
仕様書:ECMAScript 2015 Language Specification ‒ ECMA-262 6th
Edition
処理系の対応状況は ECMAScript 6 compatibility table を参考に
章立ておよび紹介の順序はこの表に従う
全機能を網羅しているわけではない
基本的に ES5 は ES3 の、ES6 は ES3, ES5 の上位互換
ES3, ES5 の機能は引き続き ES6 でも使えると思ってよい
"use strict"; で動かなくなる構文( with 文など)は避けるべき
2 / 85
TL;DR(抜粋)
オブジェクトリテラルの略記 ( {[x]: a} , {a, b} , { f(x) { ... } } )
列挙 ( for (var x of xs) )
テンプレートリテラル ( `${x} + ${y} = ${x + y}` )
分割代入 ( [x, y] = xs , {a, b} = obj )
ブロックスコープ変数 ( let ) , 定数 ( const )
アロー関数 ( (x, y) => { ... } )
クラス ( class , extends , super )
ジェネレータ ( function * , yield )
Promise
3 / 85
目次
最適化 (Optimization)
文法 (Syntax)
束縛 (Bindings)
関数 (Functions)
ビルトイン (Built-ins)
ビルトイン拡張 (Built-in extensions)
サブクラス化 (Subclassing)
モジュール (Modules)
4 / 85
最適化 (Optimization)
末尾呼び出し最適化
5 / 85
末尾呼び出し最適化
ES6
function gcd(m, n) {
if (n === 0) {
return m;
} else {
return gcd(n, m % n);
}
}
ES6 処理系では関数末尾での再帰呼び出しが最適化される(はず)
参考:BabelとTraceurでES6末尾再帰最適化を試す - teppeis blog
6 / 85
文法 (Syntax)
デフォルト引数 ( function (x, y = 42) )
可変長引数 ( function (x, ...ys) )
配列の展開 ( f(...xs) , [x, ...ys, z] )
オブジェクトリテラルの略記 ( {[x]: a} , {a, b} , { f(x) { ... } } )
2進数 / 8進数リテラル ( 0b1010 , 0o755 )
列挙 ( for (var x of xs) )
テンプレートリテラル ( `${x} + ${y} = ${x + y}` )
新しい正規表現のフラグ ( /.../y , /🍣 🍺*🍖/u )
分割代入 ( [x, y] = xs , {a, b} = obj )
7 / 85
デフォルト引数
ES3 / ES5
function myPow(x, y) {
if (typeof y === "undefined") y = 2;
return Math.pow(x, y);
}
console.log(myPow(3)); // 9
console.log(myPow(2, 10)); // 1024
8 / 85
デフォルト引数
ES6
function myPow(x, y = 2) {
return Math.pow(x, y);
}
console.log(myPow(3)); // 9
console.log(myPow(2, 10)); // 1024
「デフォルト値を持つ引数」の後に「デフォルト引数を持たない引数」を置い
てはならない
function (x = 2, y) はダメ
9 / 85
可変長引数
ES3 / ES5
function f(x) {
console.log(x, Array.prototype.slice.call(arguments, 1));
}
f(2, 3, 5); // 2 [ 3, 5 ]
arguments は Array ではない
arguments を Array に変換するややこしいイディオムが存在する
10 / 85
可変長引数
ES6
function f(x, ...ys) {
console.log(x, ys);
}
f(2, 3, 5); // 2 [ 3, 5 ]
ちなみに Array.from(arguments) で配列に変換することもできる
11 / 85
配列の展開(引数編)
ES3 / ES5
function f(x, y, z) {
console.log(x + y * z);
}
f.apply(null, [2, 3, 5]); // 17
12 / 85
配列の展開(引数編)
ES6
function f(x, y, z) {
console.log(x + y * z);
}
f(...[2, 3, 5]); // 17
13 / 85
配列の展開(配列リテラル編)
ES3 / ES5
var xs = [5, 7];
var ys = [2, 3].concat(xs, [11, 13])
console.log(ys); // [ 2, 3, 5, 7, 11, 13 ]
14 / 85
配列の展開(配列リテラル編)
ES6
var xs = [5, 7];
var ys = [2, 3, ...xs, 11, 13];
console.log(ys); // [ 2, 3, 5, 7, 11, 13 ]
15 / 85
式をプロパティ名に使う
ES3 / ES5
var key = "foo";
var obj = {};
obj[key] = "bar";
console.log(obj); // { "foo" : "bar" }
16 / 85
式をプロパティ名に使う
ES6
var key = "foo";
var obj = {[key]: "bar"};
console.log(obj); // { "foo" : "bar" }
17 / 85
プロパティ名の略記
ES3 / ES5
var x = 2, y = 3, z = 5;
var obj = {x: x, y: y, z: z};
18 / 85
プロパティ名の略記
ES6
var x = 2, y = 3, z = 5;
var obj = {x, y, z};
変数名とプロパティ名が同じ場合に略記できる
19 / 85
メソッドの略記
ES3 / ES5
var obj = {
f: function (x) {
console.log(x * this.y);
},
y: 42
};
20 / 85
メソッドの略記
ES6
var obj = {
f(x) {
console.log(x * this.y);
},
y: 42
};
21 / 85
列挙 ( for ‒ of )
ES3 (BAD)
var xs = [2, 3, 5];
for (var i in xs) {
console.log(xs[i]);
}
javascript - Why is using "for...in" with array iteration such a bad idea?
- Stack Overflow
var xs = []; xs[5] = 42; のようなパターンでアウト
Array.prototype を弄るわるいライブラリがいるとアウト
22 / 85
列挙 ( for ‒ of )
ES3 (GOOD)
var xs = [2, 3, 5];
for (var i = 0; i < xs.length; ++i) {
console.log(xs[i]);
}
23 / 85
列挙 ( for ‒ of )
ES5
var xs = [2, 3, 5];
xs.forEach(function (x, i) {
console.log(x);
});
Array.prototype.forEach を使う
コールバック関数の第 2 引数には添字が入っている
24 / 85
列挙 ( for ‒ of )
ES6
var xs = [2, 3, 5];
for (var x of xs) {
console.log(x);
}
配列だけでなくジェネレータ(後述)なども列挙できる
Symbol.iterator (後述)を利用すれば独自のオブジェクトも列挙でき
る
25 / 85
2進数 / 8進数リテラル
ES6
console.log(0b1010); // 10
console.log(0o755); // 493
b / o は小文字でも大文字でも可
26 / 85
テンプレートリテラル
ES3 / ES5
var a = 7, b = 8;
console.log(a + " + " + b + " = " + (a + b));
27 / 85
テンプレートリテラル
ES6
var a = 7, b = 8;
console.log(`${a} + ${b} = ${a + b}`);
28 / 85
新しい正規表現のフラグ ( y , u )
ES6
var re = /(d+).?/y;
var ip = "127.0.0.1";
while (re.exec(ip)) console.log(re.lastIndex); // 4 6 8 9
sticky flag ( lastIndex から順次検索)
console.log(/🍣 🍺 *🍖 /.test("🍣 🍺 🍺 🍺 🍖 ")); // false
console.log(/🍣 🍺 *🍖 /u.test("🍣 🍺 🍺 🍺 🍖 ")); // true
参考:Unicode-aware regular expressions in ECMAScript 6 · Mathias
Bynens
29 / 85
分割代入
ES3 / ES5
var xs = [2, 3, 5];
var x = xs[0], y = xs[1], z = xs[2];
var obj = {x: 2, y: 3, nested: {z: 5}};
var x = obj.x, y = obj.y, z = obj.nested.z;
var obj = {x: 2, y: 3, nested: {z: 5}};
var a = obj.x, b = obj.y, c = obj.nested.z;
30 / 85
分割代入
ES6
var xs = [2, 3, 5];
var [x, y, z] = xs;
var obj = {x: 2, y: 3, nested: {z: 5}};
var {x, y, nested: {z}} = obj;
var obj = {x: 2, y: 3, nested: {z: 5}};
var {x: a, y: b, nested: {z: c}} = obj;
xs , obj が 1 回しか登場しないのが利点
関数の戻り値を扱う場合一時変数に代入する必要がない
変数名が長い場合にもアドバンテージ
31 / 85
束縛 (Bindings)
ブロックスコープ変数 ( let )
定数 ( const )
32 / 85
ブロックスコープ変数 ( let )
ES3 / ES5 (BAD)
var s = "foo";
{
var s = "bar";
console.log(s); // bar
}
console.log(s); // bar
ES5 以前の JavaScript には関数スコープしか存在しない
33 / 85
ブロックスコープ変数 ( let )
ES3 / ES5 (GOOD)
var s = "foo";
(function () {
var s = "bar";
console.log(s); // bar
})();
console.log(s); // foo
関数の即時実行でスコープを実現する
34 / 85
ブロックスコープ変数 ( let )
ES6
var s = "foo";
{
let s = "bar";
console.log(s); // bar
}
console.log(s); // foo
let で変数を宣言するとブロックスコープを持つ変数になる
35 / 85
let と for
ES3 / ES5 (BAD)
var fs = [];
for (var i = 0; i < 3; ++i) {
var f = function () {
console.log(i);
};
fs.push(f);
}
for (var i = 0; i < 3; ++i) {
fs[i](); // 3, 3, 3
}
クロージャが同じ i を参照している
36 / 85
let と for
ES3 / ES5 (GOOD)
var fs = [];
for (var i = 0; i < 3; ++i) {
var f = (function (i) {
return function () { console.log(i); };
})(i);
fs.push(f);
}
for (var i = 0; i < 3; ++i) {
fs[i](); // 0, 1, 2
}
関数の即時実行でスコープを切る
37 / 85
let と for
ES6
var fs = [];
for (let i = 0; i < 3; ++i) {
var f = function () {
console.log(i);
};
fs.push(f);
}
for (var i = 0; i < 3; ++i) {
fs[i](); // 0, 1, 2
}
for の初期化節で let を使う
38 / 85
定数 ( const )
ES6
const answer = 42;
answer = 0; // compile error
代入禁止
const s = "foo";
{
const s = "bar";
console.log(s); // bar
}
console.log(s); // foo
const もブロックスコープを持つ
39 / 85
関数 (Functions)
アロー関数 ( (x, y) => { ... } )
クラス ( class , extends , super )
ジェネレータ ( function * , yield )
40 / 85
アロー関数
ES3 / ES5
var myRandom = function (x, y) {
var range = y - x;
return x + (Math.random() * range);
};
var pow2 = function (x) { return x * x };
41 / 85
アロー関数
ES6
var myRandom = (x, y) => {
var range = y - x;
return x + (Math.random() * range);
};
var pow2 = x => x * x;
引数が 1 個の場合 (x) => { ... } を x => { ... } と略記可
(foo) => { return bar; } を (foo) => bar と略記可
アロー記法と function 記法では this の扱いについて違いがある
42 / 85
アロー関数( this の扱い)
ES3 / ES5 (BAD)
var obj = {
f: function () {
setTimeout(function () {
console.log(this.x);
}, 1000);
},
x: 42
};
obj.f(); // undefined
this !== obj となってしまう
43 / 85
アロー関数( this の扱い)
ES3 (GOOD)
var obj = {
f: function () {
var that = this;
setTimeout(function () {
console.log(that.x);
}, 1000);
},
x: 42
};
obj.f(); // 42
this に別名を付ける
44 / 85
アロー関数( this の扱い)
ES5 (GOOD)
var obj = {
f: function () {
setTimeout((function () {
console.log(this.x);
}).bind(this), 1000);
},
x: 42
};
obj.f(); // 42
Function.prototype.bind を使う
45 / 85
アロー関数( this の扱い)
ES6
var obj = {
f: function () {
setTimeout(() => {
console.log(this.x);
}, 1000);
},
x: 42
};
obj.f(); // 42
アロー記法の場合関数外の this を関数内でも使える ( this === obj )
クラスを使う際に特に威力を発揮する
46 / 85
クラス ( class )
ES3 / ES5
JavaScript はプロトタイプベースのオブジェクト指向言語であり、ES5 以前
にクラスは存在しない
class という単語自体は古くから予約語だったりする
ES5 以前でもクラスや継承を実現するパターンは存在する
CoffeescriptとTypescriptから学ぶjsでのクラス・継承パターン ¦ WEB
EGG
47 / 85
クラス ( class )
ES6
class Application {
constructor(name) {
this.name = name;
}
start() {
document.addEventListener("DOMContentLoaded", (event) => {
this.domDidLoad(event);
});
}
domDidLoad(event) {
console.log(event);
console.log(this);
console.log(`Application ${this.name} start...`);
}
}
48 / 85
クラスの継承 ( extends , super )
ES6
class MyApplication extends Application {
constructor(name, canvasId, fps = 60) {
super(name);
this.canvasId = canvasId;
this.fps = fps;
}
domDidLoad(event) {
super.domDidLoad(event);
this.canvas = document.getElementById(this.canvasId);
this.context = this.canvas.getContext("2d");
setTimeout(() => this.draw(this.context), 1000 / this.fps);
}
draw(ctx) {
ctx.fillStyle = "#def";
ctx.fillRect(0, 0, 640, 480);
}
}
49 / 85
クラス( this の扱い)
ES6 (GOOD)
document.addEventListener("DOMContentLoaded", (event) => {
this.domDidLoad(event);
});
setTimeout(() => this.draw(this.context), 1000 / this.fps);
クラスのコードより抜粋
アロー関数大活躍
50 / 85
クラス( this の扱い)
ES6 (BAD)
document.addEventListener("DOMContentLoaded", function (event) {
this.domDidLoad(event);
});
setTimeout(function () { this.draw(this.context); }, 1000 / this.fps);
function でこう書くことはできない
51 / 85
クラス( this の扱い)
ES6 (BAD)
document.addEventListener("DOMContentLoaded", this.domDidLoad);
こう書くこともできない
52 / 85
クラス( this の扱い)
ES6 (GOOD) (2)
document.addEventListener("DOMContentLoaded", this.domDidLoad.bind(this));
setTimeout(this.draw.bind(this, this.context), 1000 / this.fps);
Function.prototype.bind を使う場合
53 / 85
ジェネレータ
ES6
function * range(n) {
for (var i = 0; i < n; ++i) yield i;
}
const gen = range(3);
console.log(gen.next()); // { value: 0, done: false }
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: undefined, done: true }
function * と yield で中断できる関数を作ることができる
いわゆる coroutine
54 / 85
ジェネレータの列挙
ES6
function * range(n) {
for (var i = 0; i < n; ++i) yield i;
}
for (var i of range(3)) {
console.log(i); // 0, 1, 2
}
for ‒ of でジェネレータの値を列挙できる
55 / 85
ジェネレータの展開
ES6
function * range(n) {
for (var i = 0; i < n; ++i) yield i;
}
console.log([...range(2), ...range(3)]); // [ 0, 1, 0, 1, 2 ]
... でジェネレータを展開できる
56 / 85
ビルトイン (Built-ins)
型付き配列 ( Uint8Array , Float32Array , ..., DataView )
Map , WeakMap , Set , WeakSet
Proxy , Reflect
Promise
Symbol
57 / 85
型付き配列
ES6
var xs = new Float32Array(3);
console.log(xs); // [ 0, 0, 0 ]
var ys = new Uint8Array([-1, 0, 255, 256]);
console.log(ys); // [ 255, 0, 255, 0 ]
var zs = new Uint8ClampedArray([-1, 0, 255, 256]);
console.log(zs); // [ 0, 0, 255, 255 ]
XHR で取得したバイナリを扱う際に有用
WebGL を使う際にも利用する
new の際に配列長か Array か ArrayBuffer を与える
58 / 85
ArrayBuffer と型付き配列
ES6
var buf = new ArrayBuffer(8);
var f64 = new Float64Array(buf);
var i32 = new Int32Array(buf);
var ui8 = new Uint8Array(buf);
f64[0] = 0.1;
console.log(f64); // [0.1]
console.log(i32); // [-1717986918, 1069128089]
console.log(ui8); // [154, 153, 153, 153, 153, 153, 185, 63]
型付き配列は view(窓)に過ぎず、実体は ArrayBuffer である
ArrayBuffer を共有すると内容も共有される
59 / 85
DataView
ES6
var buf = new ArrayBuffer(4);
var view = new DataView(buf);
view.setUint8(0, 0xA0);
console.log(view.getInt32(0)); // -1610612736
console.log(view.getInt32(0, true)); // 160
C の構造体のような複合データを扱う際には DataView を用いるとよい
get 系関数の第 2 引数、set 系関数の第 3 引数にはエンディアンを指定する
デフォルトはビッグエンディアン
リトルエンディアンなら true を指定
60 / 85
Map
ES6
var map = new Map();
var key1 = {};
var key2 = {};
var key3 = key1;
map.set(key1, "foo");
map.set(key2, "bar");
console.log(map.get(key2)); // bar
console.log(map.get(key3)); // foo
for (var key of map.keys()) console.log(key); // {} {}
いわゆる辞書型
キーにオブジェクトを使うことができる
61 / 85
WeakMap
ES6
var map = new WeakMap();
var key1 = {};
var key2 = {};
var key3 = key1;
map.set(key1, "foo");
map.set(key2, "bar");
console.log(map.get(key2)); // bar
console.log(map.get(key3)); // foo
console.log(typeof map.keys === "undefined"); // true
キーを弱参照で持つ Map
キーを列挙することはできない
62 / 85
Set
ES6
var set = new Set([1, 1, 2, 3, 5, 8]);
set.add(2).add(3).add(5).add(7).add(11);
console.log(set); // [ 1, 2, 3, 5, 8, 7, 11 ]
console.log(set.has(4)); // false
console.log(set.has(5)); // true
いわゆる集合型
列挙は挿入順
63 / 85
WeakSet
ES6
var set = new WeakSet();
var key1 = {};
var key2 = {};
var key3 = key1;
set.add(key1);
console.log(set.has(key2)); // false
console.log(set.has(key3)); // true
キー(値)を弱参照で持つ Set
WeakMap と同じく列挙不可
64 / 85
Proxy
ES6
var obj = {};
var handler = {
get(target, name) { return target[name] / 2; },
set(target, name, val) { target[name] = val * 2; }
};
var proxy1 = new Proxy(obj, handler);
var proxy2 = new Proxy(proxy1, handler);
var proxy3 = new Proxy(proxy2, handler);
proxy3.foo = 42;
console.log(proxy3.foo); // 42
console.log(proxy2.foo); // 84
console.log(proxy1.foo); // 168
console.log(obj); // { "foo" : 336 }
メタプログラミングに使えるらしい
参考:Meta programming with ECMAScript 6 proxies
65 / 85
Reflect
ES6
var obj = {};
var handler = {
get(target, name) { return Reflect.get(target, name) / 2; },
set(target, name, val) { Reflect.set(target, name, val * 2); }
};
var proxy1 = new Proxy(obj, handler);
var proxy2 = new Proxy(proxy1, handler);
var proxy3 = new Proxy(proxy2, handler);
proxy3.foo = 42;
console.log(proxy3.foo); // 42
console.log(proxy2.foo); // 42
console.log(proxy1.foo); // 42
console.log(obj); // { "foo" : 84 }
参考:ecmascript 6 - What does the Reflect object do in JavaScript? -
Stack Overflow
66 / 85
Promise
ES6
非同期処理をうまく扱うための仕組み
参考:JavaScript Promiseの本
then のメソッドチェーンで処理順を制御し、 catch でエラー処理をする
非同期処理を行うライブラリを作る際には Promise オブジェクトを返す API
を用意しておくとよい
petkaantonov/bluebird などの polyfill が存在
67 / 85
Promise
ES6
new Promise((resolve, reject) => {
setTimeout(() => resolve("A"), 1000);
}).then((str) => {
console.log(str); // A
return new Promise((resolve, reject) => {
setTimeout(() => resolve("B"), 1000);
}).then((str) => {
console.log(str); // B
return Promise.reject(new Error("C"));
});
}).catch((err) => {
console.log(err.message); // C
return "D";
}).then((str) => {
console.log(str); // D
});
console.log("Start!");
Start! → A → B → C → D の順に表示される
68 / 85
Symbol
ES6
var sym1 = Symbol("foo");
var sym2 = Symbol("bar");
var sym3 = Symbol("bar");
console.log(sym1 == sym2); // false
console.log(sym2 == sym3); // false
console.log(sym3 == sym1); // false
一意なキーの生成などに利用
参考:Symbolについて - JS.next
69 / 85
Symbol.iterator
ES6
var obj = { };
obj[Symbol.iterator] = function () {
return {
next: function () {
return (this.i < 3) ?
{done: false, value: this.i++} : {done: true};
},
i: 0
}
};
for (var x of obj) console.log(x); // 0 1 2
自前のオブジェクトを for ‒ of で列挙できる
参考:ES6のイテレータについて調べた - ひよこ3分07秒のTechブログ
70 / 85
ビルトイン拡張 (Built-in
extensions)
Oject.assign
Object.setPrototypeOf
関数名の取得
String
Array
Number
Math
71 / 85
Object.assign
ES6
var obj = {foo: "bar", x: 42};
Object.assign(obj, {foo: "baz"}, {hoge: "piyo"});
console.log(obj); // { "foo" : "baz", "x" : 42 , "hoge" : "piyo" }
オブジェクトのマージ
72 / 85
Object.setPrototypeOf
ES6
var proto = {hoge: "piyo"};
var obj = {foo: "bar"};
Object.setPrototypeOf(obj, proto);
console.log(Object.getPrototypeOf(obj) === proto); // true
console.log(obj.foo); // bar
console.log(obj.hoge); // piyo
obj.hoge = "fuga";
console.log(obj.hoge); // fuga
オブジェクトのプロトタイプを設定する
いわゆる __proto__ の代替として利用可
73 / 85
関数名の取得
ES6
function foo() { }
console.log(foo.name); // foo
var bar = function () { };
console.log(bar.name); // bar
console.log((function () { }).name === "") // true
name プロパティで関数名を取得できる
74 / 85
String
ES6
console.log("🍣 ".codePointAt(0)); // 127843
console.log(String.fromCodePoint(12354, 32, 127843)); // あ 🍣
console.log("A".repeat(3)); // AAA
console.log("heart".includes("ear")); // true
console.log("heart".startsWith("hear")); // true
console.log("heart".startsWith("ear", 1)); // true
console.log("heart".endsWith("art")); // true
75 / 85
Array
ES6
var obj = {0: "foo", 1: "bar", length: 2};
console.log(Array.from(obj)); // ["foo", "bar"]
function * gen() { yield 2; yield 3; yield 5; }
console.log(Array.from(gen())); // [2, 3, 5]
console.log([2, 3, 5, 7].find(x => x > 3)); // 5
console.log([2, 3, 5, 7].findIndex(x => x > 3)); // 2
console.log(new Array(3).fill(42)); // [42, 42, 42]
from : 「配列のような」オブジェクトを配列に変換
find : 条件に一致する最初の要素を得る
findIndex : 条件に一致する最初の要素の添字を得る
76 / 85
Number
ES6
console.log(Number.isFinite(42)); // true
console.log(Number.isFinite(-Infinity)); // false
console.log(Number.isFinite(NaN)); // false
console.log(Number.isInteger(42.00000)); // true
console.log(Number.isInteger(42.00001)); // false
console.log(Number.isSafeInteger(1e+15)); // true
console.log(Number.isSafeInteger(1e+16)); // false
console.log(Number.EPSILON); // 2.220446049250313e-16
console.log(Number.MIN_SAFE_INTEGER); // -9007199254740991
console.log((Number.MIN_SAFE_INTEGER - 1) | 0); // 0
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
console.log((Number.MAX_SAFE_INTEGER + 1) | 0); // 0
77 / 85
Math
ES6
console.log(Math.sign(-42)); // -1
console.log(Math.cosh(Math.log(2))); // 1.25
console.log(Math.trunc(-3.5)); // -3
console.log(Math.cbrt(27)); // 3
console.log(Math.hypot(3, 4)); // 5
sign : 符号(-1, 0, +1)
cosh , sinh , tanh : 双曲線関数
trunc : 0 方向への丸め
cbrt : 立方根
hypot : 二乗和の平方根
78 / 85
サブクラス化 (Subclassing)
Array , RegExp , Function , Promise , Boolean , Number , String ,
Map , Set を継承したクラスを定義できる
79 / 85
モジュール (Modules)
import , export
80 / 85
import , export
CommonJS
// app.js
var utils = require("./utils");
utils.hello(); // Hello, world!
console.log(utils.answer); // 42
// utils.js
function hello() { console.log("Hello, world!"); }
var answer = 42;
module.exports = { hello: hello, answer: answer };
81 / 85
import , export
ES6
// app.js
import utils from "./utils";
utils.hello(); // Hello, world!
console.log(utils.answer); // 42
// utils.js
function hello() { console.log("Hello, world!"); }
var answer = 42;
export default { hello: hello, answer: answer };
クラスなども export 可能
参考:Babelで理解するEcmaScript6の import / export - Qiita
82 / 85
import * as
ES6
// app.js
import * as utils from "./utils";
utils.hello(); // Hello, world!
console.log(utils.answer); // 42
// utils.js
export function hello() { console.log("Hello, world!"); }
export var answer = 42;
83 / 85
import { ... }
ES6
// app.js
import { hello, answer } from "./utils";
hello(); // Hello, world!
console.log(answer); // 42
// utils.js
export function hello() { console.log("Hello, world!"); }
export var answer = 42;
84 / 85
END
We are hiring!
http://unipro.co.jp/
85 / 85

More Related Content

PDF
BOF1-Scala02.pdf
PPTX
Nds meetup8 lt
PPT
言語処理系入門€6
PDF
Javaセキュアコーディングセミナー東京第3回演習の解説
PDF
Patterns and Matching in Rust
PDF
JavaScript 講習会 #1
PDF
PFDS 10.2.1 lists with efficient catenation
PPTX
【LT版】Elixir入門「第7回:Python/KerasをElixirから繋いでアレコレする」
BOF1-Scala02.pdf
Nds meetup8 lt
言語処理系入門€6
Javaセキュアコーディングセミナー東京第3回演習の解説
Patterns and Matching in Rust
JavaScript 講習会 #1
PFDS 10.2.1 lists with efficient catenation
【LT版】Elixir入門「第7回:Python/KerasをElixirから繋いでアレコレする」

What's hot (20)

PPTX
大人のお型付け
ODP
Ekmett勉強会発表資料
PDF
Ekmett勉強会発表資料
PDF
Scala の関数型プログラミングを支える技術
PDF
初めてのHaskell (表)
PPTX
Java Puzzlers JJUG CCC 2016
PDF
Java SE 8 lambdaで変わる プログラミングスタイル
PPT
ジェネリクスの基礎と クラス設計への応用
PDF
Van laarhoven lens
PPT
言語処理系入門€5
PDF
JavaのGenericsとは?
PDF
C++ マルチスレッドプログラミング
PDF
20150302 java8 第一回_ラムダ式(1)
PDF
Lisp Tutorial for Pythonista : Day 3
PPTX
冬のLock free祭り safe
PDF
Metaprogramming in JuliaLang
PDF
ALPSチュートリアル(4) Python入門
PPTX
【java8 勉強会】 怖くない!ラムダ式, Stream API
PDF
「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」
PDF
JavaScript (ECMAScript) 2013
大人のお型付け
Ekmett勉強会発表資料
Ekmett勉強会発表資料
Scala の関数型プログラミングを支える技術
初めてのHaskell (表)
Java Puzzlers JJUG CCC 2016
Java SE 8 lambdaで変わる プログラミングスタイル
ジェネリクスの基礎と クラス設計への応用
Van laarhoven lens
言語処理系入門€5
JavaのGenericsとは?
C++ マルチスレッドプログラミング
20150302 java8 第一回_ラムダ式(1)
Lisp Tutorial for Pythonista : Day 3
冬のLock free祭り safe
Metaprogramming in JuliaLang
ALPSチュートリアル(4) Python入門
【java8 勉強会】 怖くない!ラムダ式, Stream API
「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」
JavaScript (ECMAScript) 2013
Ad

Viewers also liked (20)

PDF
FileReader and canvas and server silde
PDF
kontainer-js
PDF
jQuery勉強会#4
PDF
JavaScript 実践講座 Framework, Tool, Performance
PPTX
ES6 - JavaCro 2016
PPTX
Getting started with ES6 : Future of javascript
PDF
Prototypeベース in JavaScript
PDF
ES6 はじめました
PPTX
JavaScript : What is it really? AND Some new features in ES6
PDF
150421 es6とかな話
PDF
JavaScript.Next Returns
PDF
はじめてのWallaby.js
PPT
Google App EngineでTwitterアプリを作ろう
PPTX
Startup JavaScript
PDF
断言して間違えると信頼度が低下するというベイズの話
PDF
アニメーションの実装つらい話
PDF
Hello npm
PDF
Learn ES2015
PDF
Bacon.jsではじめる関数型リアアクティブプログラミング入門 with ES6
PDF
これからのJavaScriptの話
FileReader and canvas and server silde
kontainer-js
jQuery勉強会#4
JavaScript 実践講座 Framework, Tool, Performance
ES6 - JavaCro 2016
Getting started with ES6 : Future of javascript
Prototypeベース in JavaScript
ES6 はじめました
JavaScript : What is it really? AND Some new features in ES6
150421 es6とかな話
JavaScript.Next Returns
はじめてのWallaby.js
Google App EngineでTwitterアプリを作ろう
Startup JavaScript
断言して間違えると信頼度が低下するというベイズの話
アニメーションの実装つらい話
Hello npm
Learn ES2015
Bacon.jsではじめる関数型リアアクティブプログラミング入門 with ES6
これからのJavaScriptの話
Ad

Similar to ECMAScript 6 Features(PDF 版) (20)

PDF
traceur-compilerで ECMAScript6を体験
PDF
JavaScript/CSS 2015 Autumn
PPTX
PHP AST 徹底解説
PPTX
pecl-AOPの紹介
PDF
Kanazawa.js.Next
KEY
Clojure programming-chapter-2
PDF
Scala2.8への移行
PDF
Scala2.8への移行
PDF
Java8から17へ
PDF
TypeScript 言語処理系ことはじめ
PDF
第三回ありえる社内勉強会 「いわががのLombok」
PDF
PostgreSQL - C言語によるユーザ定義関数の作り方
PDF
純LISPから考える関数型言語のプリミティブ: Clojure, Elixir, Haskell, Scala
PDF
From Scala/Clojure to Kotlin
PDF
GNU awk (gawk) を用いた Apache ログ解析方法
PDF
Pfi Seminar 2010 1 7
PDF
フラグを愛でる
PPTX
Androsia:一歩先のメモリ内Androidアプリケーションデータの保護 by サミット・アンワル
PDF
BOF1-Scala02.pdf
PDF
BOF1-Scala02.pdf
traceur-compilerで ECMAScript6を体験
JavaScript/CSS 2015 Autumn
PHP AST 徹底解説
pecl-AOPの紹介
Kanazawa.js.Next
Clojure programming-chapter-2
Scala2.8への移行
Scala2.8への移行
Java8から17へ
TypeScript 言語処理系ことはじめ
第三回ありえる社内勉強会 「いわががのLombok」
PostgreSQL - C言語によるユーザ定義関数の作り方
純LISPから考える関数型言語のプリミティブ: Clojure, Elixir, Haskell, Scala
From Scala/Clojure to Kotlin
GNU awk (gawk) を用いた Apache ログ解析方法
Pfi Seminar 2010 1 7
フラグを愛でる
Androsia:一歩先のメモリ内Androidアプリケーションデータの保護 by サミット・アンワル
BOF1-Scala02.pdf
BOF1-Scala02.pdf

ECMAScript 6 Features(PDF 版)

  • 2. このスライドについて ECMAScript 6 の新機能を紹介するスライドです 仕様書:ECMAScript 2015 Language Specification ‒ ECMA-262 6th Edition 処理系の対応状況は ECMAScript 6 compatibility table を参考に 章立ておよび紹介の順序はこの表に従う 全機能を網羅しているわけではない 基本的に ES5 は ES3 の、ES6 は ES3, ES5 の上位互換 ES3, ES5 の機能は引き続き ES6 でも使えると思ってよい "use strict"; で動かなくなる構文( with 文など)は避けるべき 2 / 85
  • 3. TL;DR(抜粋) オブジェクトリテラルの略記 ( {[x]: a} , {a, b} , { f(x) { ... } } ) 列挙 ( for (var x of xs) ) テンプレートリテラル ( `${x} + ${y} = ${x + y}` ) 分割代入 ( [x, y] = xs , {a, b} = obj ) ブロックスコープ変数 ( let ) , 定数 ( const ) アロー関数 ( (x, y) => { ... } ) クラス ( class , extends , super ) ジェネレータ ( function * , yield ) Promise 3 / 85
  • 4. 目次 最適化 (Optimization) 文法 (Syntax) 束縛 (Bindings) 関数 (Functions) ビルトイン (Built-ins) ビルトイン拡張 (Built-in extensions) サブクラス化 (Subclassing) モジュール (Modules) 4 / 85
  • 6. 末尾呼び出し最適化 ES6 function gcd(m, n) { if (n === 0) { return m; } else { return gcd(n, m % n); } } ES6 処理系では関数末尾での再帰呼び出しが最適化される(はず) 参考:BabelとTraceurでES6末尾再帰最適化を試す - teppeis blog 6 / 85
  • 7. 文法 (Syntax) デフォルト引数 ( function (x, y = 42) ) 可変長引数 ( function (x, ...ys) ) 配列の展開 ( f(...xs) , [x, ...ys, z] ) オブジェクトリテラルの略記 ( {[x]: a} , {a, b} , { f(x) { ... } } ) 2進数 / 8進数リテラル ( 0b1010 , 0o755 ) 列挙 ( for (var x of xs) ) テンプレートリテラル ( `${x} + ${y} = ${x + y}` ) 新しい正規表現のフラグ ( /.../y , /🍣 🍺*🍖/u ) 分割代入 ( [x, y] = xs , {a, b} = obj ) 7 / 85
  • 8. デフォルト引数 ES3 / ES5 function myPow(x, y) { if (typeof y === "undefined") y = 2; return Math.pow(x, y); } console.log(myPow(3)); // 9 console.log(myPow(2, 10)); // 1024 8 / 85
  • 9. デフォルト引数 ES6 function myPow(x, y = 2) { return Math.pow(x, y); } console.log(myPow(3)); // 9 console.log(myPow(2, 10)); // 1024 「デフォルト値を持つ引数」の後に「デフォルト引数を持たない引数」を置い てはならない function (x = 2, y) はダメ 9 / 85
  • 10. 可変長引数 ES3 / ES5 function f(x) { console.log(x, Array.prototype.slice.call(arguments, 1)); } f(2, 3, 5); // 2 [ 3, 5 ] arguments は Array ではない arguments を Array に変換するややこしいイディオムが存在する 10 / 85
  • 11. 可変長引数 ES6 function f(x, ...ys) { console.log(x, ys); } f(2, 3, 5); // 2 [ 3, 5 ] ちなみに Array.from(arguments) で配列に変換することもできる 11 / 85
  • 12. 配列の展開(引数編) ES3 / ES5 function f(x, y, z) { console.log(x + y * z); } f.apply(null, [2, 3, 5]); // 17 12 / 85
  • 13. 配列の展開(引数編) ES6 function f(x, y, z) { console.log(x + y * z); } f(...[2, 3, 5]); // 17 13 / 85
  • 14. 配列の展開(配列リテラル編) ES3 / ES5 var xs = [5, 7]; var ys = [2, 3].concat(xs, [11, 13]) console.log(ys); // [ 2, 3, 5, 7, 11, 13 ] 14 / 85
  • 15. 配列の展開(配列リテラル編) ES6 var xs = [5, 7]; var ys = [2, 3, ...xs, 11, 13]; console.log(ys); // [ 2, 3, 5, 7, 11, 13 ] 15 / 85
  • 16. 式をプロパティ名に使う ES3 / ES5 var key = "foo"; var obj = {}; obj[key] = "bar"; console.log(obj); // { "foo" : "bar" } 16 / 85
  • 17. 式をプロパティ名に使う ES6 var key = "foo"; var obj = {[key]: "bar"}; console.log(obj); // { "foo" : "bar" } 17 / 85
  • 18. プロパティ名の略記 ES3 / ES5 var x = 2, y = 3, z = 5; var obj = {x: x, y: y, z: z}; 18 / 85
  • 19. プロパティ名の略記 ES6 var x = 2, y = 3, z = 5; var obj = {x, y, z}; 変数名とプロパティ名が同じ場合に略記できる 19 / 85
  • 20. メソッドの略記 ES3 / ES5 var obj = { f: function (x) { console.log(x * this.y); }, y: 42 }; 20 / 85
  • 21. メソッドの略記 ES6 var obj = { f(x) { console.log(x * this.y); }, y: 42 }; 21 / 85
  • 22. 列挙 ( for ‒ of ) ES3 (BAD) var xs = [2, 3, 5]; for (var i in xs) { console.log(xs[i]); } javascript - Why is using "for...in" with array iteration such a bad idea? - Stack Overflow var xs = []; xs[5] = 42; のようなパターンでアウト Array.prototype を弄るわるいライブラリがいるとアウト 22 / 85
  • 23. 列挙 ( for ‒ of ) ES3 (GOOD) var xs = [2, 3, 5]; for (var i = 0; i < xs.length; ++i) { console.log(xs[i]); } 23 / 85
  • 24. 列挙 ( for ‒ of ) ES5 var xs = [2, 3, 5]; xs.forEach(function (x, i) { console.log(x); }); Array.prototype.forEach を使う コールバック関数の第 2 引数には添字が入っている 24 / 85
  • 25. 列挙 ( for ‒ of ) ES6 var xs = [2, 3, 5]; for (var x of xs) { console.log(x); } 配列だけでなくジェネレータ(後述)なども列挙できる Symbol.iterator (後述)を利用すれば独自のオブジェクトも列挙でき る 25 / 85
  • 26. 2進数 / 8進数リテラル ES6 console.log(0b1010); // 10 console.log(0o755); // 493 b / o は小文字でも大文字でも可 26 / 85
  • 27. テンプレートリテラル ES3 / ES5 var a = 7, b = 8; console.log(a + " + " + b + " = " + (a + b)); 27 / 85
  • 28. テンプレートリテラル ES6 var a = 7, b = 8; console.log(`${a} + ${b} = ${a + b}`); 28 / 85
  • 29. 新しい正規表現のフラグ ( y , u ) ES6 var re = /(d+).?/y; var ip = "127.0.0.1"; while (re.exec(ip)) console.log(re.lastIndex); // 4 6 8 9 sticky flag ( lastIndex から順次検索) console.log(/🍣 🍺 *🍖 /.test("🍣 🍺 🍺 🍺 🍖 ")); // false console.log(/🍣 🍺 *🍖 /u.test("🍣 🍺 🍺 🍺 🍖 ")); // true 参考:Unicode-aware regular expressions in ECMAScript 6 · Mathias Bynens 29 / 85
  • 30. 分割代入 ES3 / ES5 var xs = [2, 3, 5]; var x = xs[0], y = xs[1], z = xs[2]; var obj = {x: 2, y: 3, nested: {z: 5}}; var x = obj.x, y = obj.y, z = obj.nested.z; var obj = {x: 2, y: 3, nested: {z: 5}}; var a = obj.x, b = obj.y, c = obj.nested.z; 30 / 85
  • 31. 分割代入 ES6 var xs = [2, 3, 5]; var [x, y, z] = xs; var obj = {x: 2, y: 3, nested: {z: 5}}; var {x, y, nested: {z}} = obj; var obj = {x: 2, y: 3, nested: {z: 5}}; var {x: a, y: b, nested: {z: c}} = obj; xs , obj が 1 回しか登場しないのが利点 関数の戻り値を扱う場合一時変数に代入する必要がない 変数名が長い場合にもアドバンテージ 31 / 85
  • 32. 束縛 (Bindings) ブロックスコープ変数 ( let ) 定数 ( const ) 32 / 85
  • 33. ブロックスコープ変数 ( let ) ES3 / ES5 (BAD) var s = "foo"; { var s = "bar"; console.log(s); // bar } console.log(s); // bar ES5 以前の JavaScript には関数スコープしか存在しない 33 / 85
  • 34. ブロックスコープ変数 ( let ) ES3 / ES5 (GOOD) var s = "foo"; (function () { var s = "bar"; console.log(s); // bar })(); console.log(s); // foo 関数の即時実行でスコープを実現する 34 / 85
  • 35. ブロックスコープ変数 ( let ) ES6 var s = "foo"; { let s = "bar"; console.log(s); // bar } console.log(s); // foo let で変数を宣言するとブロックスコープを持つ変数になる 35 / 85
  • 36. let と for ES3 / ES5 (BAD) var fs = []; for (var i = 0; i < 3; ++i) { var f = function () { console.log(i); }; fs.push(f); } for (var i = 0; i < 3; ++i) { fs[i](); // 3, 3, 3 } クロージャが同じ i を参照している 36 / 85
  • 37. let と for ES3 / ES5 (GOOD) var fs = []; for (var i = 0; i < 3; ++i) { var f = (function (i) { return function () { console.log(i); }; })(i); fs.push(f); } for (var i = 0; i < 3; ++i) { fs[i](); // 0, 1, 2 } 関数の即時実行でスコープを切る 37 / 85
  • 38. let と for ES6 var fs = []; for (let i = 0; i < 3; ++i) { var f = function () { console.log(i); }; fs.push(f); } for (var i = 0; i < 3; ++i) { fs[i](); // 0, 1, 2 } for の初期化節で let を使う 38 / 85
  • 39. 定数 ( const ) ES6 const answer = 42; answer = 0; // compile error 代入禁止 const s = "foo"; { const s = "bar"; console.log(s); // bar } console.log(s); // foo const もブロックスコープを持つ 39 / 85
  • 40. 関数 (Functions) アロー関数 ( (x, y) => { ... } ) クラス ( class , extends , super ) ジェネレータ ( function * , yield ) 40 / 85
  • 41. アロー関数 ES3 / ES5 var myRandom = function (x, y) { var range = y - x; return x + (Math.random() * range); }; var pow2 = function (x) { return x * x }; 41 / 85
  • 42. アロー関数 ES6 var myRandom = (x, y) => { var range = y - x; return x + (Math.random() * range); }; var pow2 = x => x * x; 引数が 1 個の場合 (x) => { ... } を x => { ... } と略記可 (foo) => { return bar; } を (foo) => bar と略記可 アロー記法と function 記法では this の扱いについて違いがある 42 / 85
  • 43. アロー関数( this の扱い) ES3 / ES5 (BAD) var obj = { f: function () { setTimeout(function () { console.log(this.x); }, 1000); }, x: 42 }; obj.f(); // undefined this !== obj となってしまう 43 / 85
  • 44. アロー関数( this の扱い) ES3 (GOOD) var obj = { f: function () { var that = this; setTimeout(function () { console.log(that.x); }, 1000); }, x: 42 }; obj.f(); // 42 this に別名を付ける 44 / 85
  • 45. アロー関数( this の扱い) ES5 (GOOD) var obj = { f: function () { setTimeout((function () { console.log(this.x); }).bind(this), 1000); }, x: 42 }; obj.f(); // 42 Function.prototype.bind を使う 45 / 85
  • 46. アロー関数( this の扱い) ES6 var obj = { f: function () { setTimeout(() => { console.log(this.x); }, 1000); }, x: 42 }; obj.f(); // 42 アロー記法の場合関数外の this を関数内でも使える ( this === obj ) クラスを使う際に特に威力を発揮する 46 / 85
  • 47. クラス ( class ) ES3 / ES5 JavaScript はプロトタイプベースのオブジェクト指向言語であり、ES5 以前 にクラスは存在しない class という単語自体は古くから予約語だったりする ES5 以前でもクラスや継承を実現するパターンは存在する CoffeescriptとTypescriptから学ぶjsでのクラス・継承パターン ¦ WEB EGG 47 / 85
  • 48. クラス ( class ) ES6 class Application { constructor(name) { this.name = name; } start() { document.addEventListener("DOMContentLoaded", (event) => { this.domDidLoad(event); }); } domDidLoad(event) { console.log(event); console.log(this); console.log(`Application ${this.name} start...`); } } 48 / 85
  • 49. クラスの継承 ( extends , super ) ES6 class MyApplication extends Application { constructor(name, canvasId, fps = 60) { super(name); this.canvasId = canvasId; this.fps = fps; } domDidLoad(event) { super.domDidLoad(event); this.canvas = document.getElementById(this.canvasId); this.context = this.canvas.getContext("2d"); setTimeout(() => this.draw(this.context), 1000 / this.fps); } draw(ctx) { ctx.fillStyle = "#def"; ctx.fillRect(0, 0, 640, 480); } } 49 / 85
  • 50. クラス( this の扱い) ES6 (GOOD) document.addEventListener("DOMContentLoaded", (event) => { this.domDidLoad(event); }); setTimeout(() => this.draw(this.context), 1000 / this.fps); クラスのコードより抜粋 アロー関数大活躍 50 / 85
  • 51. クラス( this の扱い) ES6 (BAD) document.addEventListener("DOMContentLoaded", function (event) { this.domDidLoad(event); }); setTimeout(function () { this.draw(this.context); }, 1000 / this.fps); function でこう書くことはできない 51 / 85
  • 52. クラス( this の扱い) ES6 (BAD) document.addEventListener("DOMContentLoaded", this.domDidLoad); こう書くこともできない 52 / 85
  • 53. クラス( this の扱い) ES6 (GOOD) (2) document.addEventListener("DOMContentLoaded", this.domDidLoad.bind(this)); setTimeout(this.draw.bind(this, this.context), 1000 / this.fps); Function.prototype.bind を使う場合 53 / 85
  • 54. ジェネレータ ES6 function * range(n) { for (var i = 0; i < n; ++i) yield i; } const gen = range(3); console.log(gen.next()); // { value: 0, done: false } console.log(gen.next()); // { value: 1, done: false } console.log(gen.next()); // { value: 2, done: false } console.log(gen.next()); // { value: undefined, done: true } function * と yield で中断できる関数を作ることができる いわゆる coroutine 54 / 85
  • 55. ジェネレータの列挙 ES6 function * range(n) { for (var i = 0; i < n; ++i) yield i; } for (var i of range(3)) { console.log(i); // 0, 1, 2 } for ‒ of でジェネレータの値を列挙できる 55 / 85
  • 56. ジェネレータの展開 ES6 function * range(n) { for (var i = 0; i < n; ++i) yield i; } console.log([...range(2), ...range(3)]); // [ 0, 1, 0, 1, 2 ] ... でジェネレータを展開できる 56 / 85
  • 57. ビルトイン (Built-ins) 型付き配列 ( Uint8Array , Float32Array , ..., DataView ) Map , WeakMap , Set , WeakSet Proxy , Reflect Promise Symbol 57 / 85
  • 58. 型付き配列 ES6 var xs = new Float32Array(3); console.log(xs); // [ 0, 0, 0 ] var ys = new Uint8Array([-1, 0, 255, 256]); console.log(ys); // [ 255, 0, 255, 0 ] var zs = new Uint8ClampedArray([-1, 0, 255, 256]); console.log(zs); // [ 0, 0, 255, 255 ] XHR で取得したバイナリを扱う際に有用 WebGL を使う際にも利用する new の際に配列長か Array か ArrayBuffer を与える 58 / 85
  • 59. ArrayBuffer と型付き配列 ES6 var buf = new ArrayBuffer(8); var f64 = new Float64Array(buf); var i32 = new Int32Array(buf); var ui8 = new Uint8Array(buf); f64[0] = 0.1; console.log(f64); // [0.1] console.log(i32); // [-1717986918, 1069128089] console.log(ui8); // [154, 153, 153, 153, 153, 153, 185, 63] 型付き配列は view(窓)に過ぎず、実体は ArrayBuffer である ArrayBuffer を共有すると内容も共有される 59 / 85
  • 60. DataView ES6 var buf = new ArrayBuffer(4); var view = new DataView(buf); view.setUint8(0, 0xA0); console.log(view.getInt32(0)); // -1610612736 console.log(view.getInt32(0, true)); // 160 C の構造体のような複合データを扱う際には DataView を用いるとよい get 系関数の第 2 引数、set 系関数の第 3 引数にはエンディアンを指定する デフォルトはビッグエンディアン リトルエンディアンなら true を指定 60 / 85
  • 61. Map ES6 var map = new Map(); var key1 = {}; var key2 = {}; var key3 = key1; map.set(key1, "foo"); map.set(key2, "bar"); console.log(map.get(key2)); // bar console.log(map.get(key3)); // foo for (var key of map.keys()) console.log(key); // {} {} いわゆる辞書型 キーにオブジェクトを使うことができる 61 / 85
  • 62. WeakMap ES6 var map = new WeakMap(); var key1 = {}; var key2 = {}; var key3 = key1; map.set(key1, "foo"); map.set(key2, "bar"); console.log(map.get(key2)); // bar console.log(map.get(key3)); // foo console.log(typeof map.keys === "undefined"); // true キーを弱参照で持つ Map キーを列挙することはできない 62 / 85
  • 63. Set ES6 var set = new Set([1, 1, 2, 3, 5, 8]); set.add(2).add(3).add(5).add(7).add(11); console.log(set); // [ 1, 2, 3, 5, 8, 7, 11 ] console.log(set.has(4)); // false console.log(set.has(5)); // true いわゆる集合型 列挙は挿入順 63 / 85
  • 64. WeakSet ES6 var set = new WeakSet(); var key1 = {}; var key2 = {}; var key3 = key1; set.add(key1); console.log(set.has(key2)); // false console.log(set.has(key3)); // true キー(値)を弱参照で持つ Set WeakMap と同じく列挙不可 64 / 85
  • 65. Proxy ES6 var obj = {}; var handler = { get(target, name) { return target[name] / 2; }, set(target, name, val) { target[name] = val * 2; } }; var proxy1 = new Proxy(obj, handler); var proxy2 = new Proxy(proxy1, handler); var proxy3 = new Proxy(proxy2, handler); proxy3.foo = 42; console.log(proxy3.foo); // 42 console.log(proxy2.foo); // 84 console.log(proxy1.foo); // 168 console.log(obj); // { "foo" : 336 } メタプログラミングに使えるらしい 参考:Meta programming with ECMAScript 6 proxies 65 / 85
  • 66. Reflect ES6 var obj = {}; var handler = { get(target, name) { return Reflect.get(target, name) / 2; }, set(target, name, val) { Reflect.set(target, name, val * 2); } }; var proxy1 = new Proxy(obj, handler); var proxy2 = new Proxy(proxy1, handler); var proxy3 = new Proxy(proxy2, handler); proxy3.foo = 42; console.log(proxy3.foo); // 42 console.log(proxy2.foo); // 42 console.log(proxy1.foo); // 42 console.log(obj); // { "foo" : 84 } 参考:ecmascript 6 - What does the Reflect object do in JavaScript? - Stack Overflow 66 / 85
  • 67. Promise ES6 非同期処理をうまく扱うための仕組み 参考:JavaScript Promiseの本 then のメソッドチェーンで処理順を制御し、 catch でエラー処理をする 非同期処理を行うライブラリを作る際には Promise オブジェクトを返す API を用意しておくとよい petkaantonov/bluebird などの polyfill が存在 67 / 85
  • 68. Promise ES6 new Promise((resolve, reject) => { setTimeout(() => resolve("A"), 1000); }).then((str) => { console.log(str); // A return new Promise((resolve, reject) => { setTimeout(() => resolve("B"), 1000); }).then((str) => { console.log(str); // B return Promise.reject(new Error("C")); }); }).catch((err) => { console.log(err.message); // C return "D"; }).then((str) => { console.log(str); // D }); console.log("Start!"); Start! → A → B → C → D の順に表示される 68 / 85
  • 69. Symbol ES6 var sym1 = Symbol("foo"); var sym2 = Symbol("bar"); var sym3 = Symbol("bar"); console.log(sym1 == sym2); // false console.log(sym2 == sym3); // false console.log(sym3 == sym1); // false 一意なキーの生成などに利用 参考:Symbolについて - JS.next 69 / 85
  • 70. Symbol.iterator ES6 var obj = { }; obj[Symbol.iterator] = function () { return { next: function () { return (this.i < 3) ? {done: false, value: this.i++} : {done: true}; }, i: 0 } }; for (var x of obj) console.log(x); // 0 1 2 自前のオブジェクトを for ‒ of で列挙できる 参考:ES6のイテレータについて調べた - ひよこ3分07秒のTechブログ 70 / 85
  • 72. Object.assign ES6 var obj = {foo: "bar", x: 42}; Object.assign(obj, {foo: "baz"}, {hoge: "piyo"}); console.log(obj); // { "foo" : "baz", "x" : 42 , "hoge" : "piyo" } オブジェクトのマージ 72 / 85
  • 73. Object.setPrototypeOf ES6 var proto = {hoge: "piyo"}; var obj = {foo: "bar"}; Object.setPrototypeOf(obj, proto); console.log(Object.getPrototypeOf(obj) === proto); // true console.log(obj.foo); // bar console.log(obj.hoge); // piyo obj.hoge = "fuga"; console.log(obj.hoge); // fuga オブジェクトのプロトタイプを設定する いわゆる __proto__ の代替として利用可 73 / 85
  • 74. 関数名の取得 ES6 function foo() { } console.log(foo.name); // foo var bar = function () { }; console.log(bar.name); // bar console.log((function () { }).name === "") // true name プロパティで関数名を取得できる 74 / 85
  • 75. String ES6 console.log("🍣 ".codePointAt(0)); // 127843 console.log(String.fromCodePoint(12354, 32, 127843)); // あ 🍣 console.log("A".repeat(3)); // AAA console.log("heart".includes("ear")); // true console.log("heart".startsWith("hear")); // true console.log("heart".startsWith("ear", 1)); // true console.log("heart".endsWith("art")); // true 75 / 85
  • 76. Array ES6 var obj = {0: "foo", 1: "bar", length: 2}; console.log(Array.from(obj)); // ["foo", "bar"] function * gen() { yield 2; yield 3; yield 5; } console.log(Array.from(gen())); // [2, 3, 5] console.log([2, 3, 5, 7].find(x => x > 3)); // 5 console.log([2, 3, 5, 7].findIndex(x => x > 3)); // 2 console.log(new Array(3).fill(42)); // [42, 42, 42] from : 「配列のような」オブジェクトを配列に変換 find : 条件に一致する最初の要素を得る findIndex : 条件に一致する最初の要素の添字を得る 76 / 85
  • 77. Number ES6 console.log(Number.isFinite(42)); // true console.log(Number.isFinite(-Infinity)); // false console.log(Number.isFinite(NaN)); // false console.log(Number.isInteger(42.00000)); // true console.log(Number.isInteger(42.00001)); // false console.log(Number.isSafeInteger(1e+15)); // true console.log(Number.isSafeInteger(1e+16)); // false console.log(Number.EPSILON); // 2.220446049250313e-16 console.log(Number.MIN_SAFE_INTEGER); // -9007199254740991 console.log((Number.MIN_SAFE_INTEGER - 1) | 0); // 0 console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991 console.log((Number.MAX_SAFE_INTEGER + 1) | 0); // 0 77 / 85
  • 78. Math ES6 console.log(Math.sign(-42)); // -1 console.log(Math.cosh(Math.log(2))); // 1.25 console.log(Math.trunc(-3.5)); // -3 console.log(Math.cbrt(27)); // 3 console.log(Math.hypot(3, 4)); // 5 sign : 符号(-1, 0, +1) cosh , sinh , tanh : 双曲線関数 trunc : 0 方向への丸め cbrt : 立方根 hypot : 二乗和の平方根 78 / 85
  • 79. サブクラス化 (Subclassing) Array , RegExp , Function , Promise , Boolean , Number , String , Map , Set を継承したクラスを定義できる 79 / 85
  • 81. import , export CommonJS // app.js var utils = require("./utils"); utils.hello(); // Hello, world! console.log(utils.answer); // 42 // utils.js function hello() { console.log("Hello, world!"); } var answer = 42; module.exports = { hello: hello, answer: answer }; 81 / 85
  • 82. import , export ES6 // app.js import utils from "./utils"; utils.hello(); // Hello, world! console.log(utils.answer); // 42 // utils.js function hello() { console.log("Hello, world!"); } var answer = 42; export default { hello: hello, answer: answer }; クラスなども export 可能 参考:Babelで理解するEcmaScript6の import / export - Qiita 82 / 85
  • 83. import * as ES6 // app.js import * as utils from "./utils"; utils.hello(); // Hello, world! console.log(utils.answer); // 42 // utils.js export function hello() { console.log("Hello, world!"); } export var answer = 42; 83 / 85
  • 84. import { ... } ES6 // app.js import { hello, answer } from "./utils"; hello(); // Hello, world! console.log(answer); // 42 // utils.js export function hello() { console.log("Hello, world!"); } export var answer = 42; 84 / 85