ECMAScript 6 Features(PDF 版)

taskie
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
1 of 85

Recommended

BOF1-Scala02.pdf by
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdfHiroshi Ono
344 views26 slides
Nds meetup8 lt by
Nds meetup8 ltNds meetup8 lt
Nds meetup8 ltushiboy
1.4K views53 slides
言語処理系入門€6 by
言語処理系入門€6言語処理系入門€6
言語処理系入門€6Kenta Hattori
1.2K views24 slides
Javaセキュアコーディングセミナー東京第3回演習の解説 by
Javaセキュアコーディングセミナー東京第3回演習の解説Javaセキュアコーディングセミナー東京第3回演習の解説
Javaセキュアコーディングセミナー東京第3回演習の解説JPCERT Coordination Center
416 views18 slides
Patterns and Matching in Rust by
Patterns and Matching in RustPatterns and Matching in Rust
Patterns and Matching in RustDaichiMukai1
118 views17 slides
JavaScript 講習会 #1 by
JavaScript 講習会 #1JavaScript 講習会 #1
JavaScript 講習会 #1Susisu
2.8K views60 slides

More Related Content

What's hot

大人のお型付け by
大人のお型付け大人のお型付け
大人のお型付けNobuhisa Koizumi
1.5K views30 slides
Ekmett勉強会発表資料 by
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料時響 逢坂
948 views68 slides
Ekmett勉強会発表資料 by
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料時響 逢坂
16.7K views77 slides
Scala の関数型プログラミングを支える技術 by
Scala の関数型プログラミングを支える技術Scala の関数型プログラミングを支える技術
Scala の関数型プログラミングを支える技術Naoki Aoyama
9.9K views59 slides
初めてのHaskell (表) by
初めてのHaskell (表)初めてのHaskell (表)
初めてのHaskell (表)karky7
42 views94 slides
Java Puzzlers JJUG CCC 2016 by
Java Puzzlers JJUG CCC 2016Java Puzzlers JJUG CCC 2016
Java Puzzlers JJUG CCC 2016Yoshio Terada
7.1K views48 slides

What's hot(20)

Ekmett勉強会発表資料 by 時響 逢坂
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料
時響 逢坂948 views
Ekmett勉強会発表資料 by 時響 逢坂
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料
時響 逢坂16.7K views
Scala の関数型プログラミングを支える技術 by Naoki Aoyama
Scala の関数型プログラミングを支える技術Scala の関数型プログラミングを支える技術
Scala の関数型プログラミングを支える技術
Naoki Aoyama9.9K views
初めてのHaskell (表) by karky7
初めてのHaskell (表)初めてのHaskell (表)
初めてのHaskell (表)
karky742 views
Java Puzzlers JJUG CCC 2016 by Yoshio Terada
Java Puzzlers JJUG CCC 2016Java Puzzlers JJUG CCC 2016
Java Puzzlers JJUG CCC 2016
Yoshio Terada7.1K views
Java SE 8 lambdaで変わる プログラミングスタイル by なおき きしだ
Java SE 8 lambdaで変わる プログラミングスタイルJava SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイル
ジェネリクスの基礎と クラス設計への応用 by nagise
ジェネリクスの基礎とクラス設計への応用ジェネリクスの基礎とクラス設計への応用
ジェネリクスの基礎と クラス設計への応用
nagise30.6K views
Van laarhoven lens by Naoki Aoyama
Van laarhoven lensVan laarhoven lens
Van laarhoven lens
Naoki Aoyama1.9K views
言語処理系入門€5 by Kenta Hattori
言語処理系入門€5言語処理系入門€5
言語処理系入門€5
Kenta Hattori427 views
C++ マルチスレッドプログラミング by Kohsuke Yuasa
C++ マルチスレッドプログラミングC++ マルチスレッドプログラミング
C++ マルチスレッドプログラミング
Kohsuke Yuasa107.6K views
Lisp Tutorial for Pythonista : Day 3 by Ransui Iso
Lisp Tutorial for Pythonista : Day 3Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3
Ransui Iso3.3K views
ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2 by Masatoshi Tada
ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2
ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2
Masatoshi Tada54.9K views
【java8 勉強会】 怖くない!ラムダ式, Stream API by dcomsolution
【java8 勉強会】 怖くない!ラムダ式, Stream API【java8 勉強会】 怖くない!ラムダ式, Stream API
【java8 勉強会】 怖くない!ラムダ式, Stream API
dcomsolution6.4K views
「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」 by Nagi Teramo
「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」
「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」
Nagi Teramo26.3K views

Viewers also liked

FileReader and canvas and server silde by
FileReader and canvas and server sildeFileReader and canvas and server silde
FileReader and canvas and server sildeNet Kanayan
568 views34 slides
kontainer-js by
kontainer-jskontainer-js
kontainer-jsKuu Miyazaki
966 views18 slides
jQuery勉強会#4 by
jQuery勉強会#4jQuery勉強会#4
jQuery勉強会#4Ryo Maruyama
1K views19 slides
JavaScript 実践講座 Framework, Tool, Performance by
JavaScript 実践講座 Framework, Tool, PerformanceJavaScript 実践講座 Framework, Tool, Performance
JavaScript 実践講座 Framework, Tool, Performanceクラスメソッド株式会社
2.1K views54 slides
ES6 - JavaCro 2016 by
ES6 - JavaCro 2016ES6 - JavaCro 2016
ES6 - JavaCro 2016Nenad Pecanac
380 views38 slides
Getting started with ES6 : Future of javascript by
Getting started with ES6 : Future of javascriptGetting started with ES6 : Future of javascript
Getting started with ES6 : Future of javascriptMohd Saeed
1K views34 slides

Viewers also liked(20)

FileReader and canvas and server silde by Net Kanayan
FileReader and canvas and server sildeFileReader and canvas and server silde
FileReader and canvas and server silde
Net Kanayan568 views
Getting started with ES6 : Future of javascript by Mohd Saeed
Getting started with ES6 : Future of javascriptGetting started with ES6 : Future of javascript
Getting started with ES6 : Future of javascript
Mohd Saeed1K views
Prototypeベース in JavaScript by Ryo Maruyama
Prototypeベース in JavaScriptPrototypeベース in JavaScript
Prototypeベース in JavaScript
Ryo Maruyama685 views
ES6 はじめました by Net Kanayan
ES6 はじめましたES6 はじめました
ES6 はじめました
Net Kanayan784 views
JavaScript : What is it really? AND Some new features in ES6 by Aayush Shrestha
JavaScript : What is it really? AND Some new features in ES6JavaScript : What is it really? AND Some new features in ES6
JavaScript : What is it really? AND Some new features in ES6
Aayush Shrestha583 views
JavaScript.Next Returns by dynamis
JavaScript.Next ReturnsJavaScript.Next Returns
JavaScript.Next Returns
dynamis 7K views
はじめてのWallaby.js by Shunta Saito
はじめてのWallaby.jsはじめてのWallaby.js
はじめてのWallaby.js
Shunta Saito2.5K views
Google App EngineでTwitterアプリを作ろう by kenji4569
Google App EngineでTwitterアプリを作ろうGoogle App EngineでTwitterアプリを作ろう
Google App EngineでTwitterアプリを作ろう
kenji45691.4K views
断言して間違えると信頼度が低下するというベイズの話 by Junya Hayashi
断言して間違えると信頼度が低下するというベイズの話断言して間違えると信頼度が低下するというベイズの話
断言して間違えると信頼度が低下するというベイズの話
Junya Hayashi770 views
アニメーションの実装つらい話 by kata shin
アニメーションの実装つらい話アニメーションの実装つらい話
アニメーションの実装つらい話
kata shin943 views
Bacon.jsではじめる関数型リアアクティブプログラミング入門 with ES6 by Haraguchi Go
Bacon.jsではじめる関数型リアアクティブプログラミング入門 with ES6Bacon.jsではじめる関数型リアアクティブプログラミング入門 with ES6
Bacon.jsではじめる関数型リアアクティブプログラミング入門 with ES6
Haraguchi Go4.7K views
これからのJavaScriptの話 by Shogo Sensui
これからのJavaScriptの話これからのJavaScriptの話
これからのJavaScriptの話
Shogo Sensui4.3K views

Similar to ECMAScript 6 Features(PDF 版)

JavaScript (ECMAScript) 2013 by
JavaScript (ECMAScript) 2013JavaScript (ECMAScript) 2013
JavaScript (ECMAScript) 2013dynamis
14.7K views100 slides
traceur-compilerで ECMAScript6を体験 by
traceur-compilerで ECMAScript6を体験traceur-compilerで ECMAScript6を体験
traceur-compilerで ECMAScript6を体験Toshio Ehara
1.2K views48 slides
JavaScript/CSS 2015 Autumn by
JavaScript/CSS 2015 AutumnJavaScript/CSS 2015 Autumn
JavaScript/CSS 2015 AutumnKoji Ishimoto
18.3K views131 slides
PHP AST 徹底解説 by
PHP AST 徹底解説PHP AST 徹底解説
PHP AST 徹底解説do_aki
26.4K views77 slides
pecl-AOPの紹介 by
pecl-AOPの紹介pecl-AOPの紹介
pecl-AOPの紹介Hiraku Nakano
2.1K views28 slides
Kanazawa.js.Next by
Kanazawa.js.NextKanazawa.js.Next
Kanazawa.js.Nextdynamis
1.6K views84 slides

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

JavaScript (ECMAScript) 2013 by dynamis
JavaScript (ECMAScript) 2013JavaScript (ECMAScript) 2013
JavaScript (ECMAScript) 2013
dynamis 14.7K views
traceur-compilerで ECMAScript6を体験 by Toshio Ehara
traceur-compilerで ECMAScript6を体験traceur-compilerで ECMAScript6を体験
traceur-compilerで ECMAScript6を体験
Toshio Ehara1.2K views
JavaScript/CSS 2015 Autumn by Koji Ishimoto
JavaScript/CSS 2015 AutumnJavaScript/CSS 2015 Autumn
JavaScript/CSS 2015 Autumn
Koji Ishimoto18.3K views
PHP AST 徹底解説 by do_aki
PHP AST 徹底解説PHP AST 徹底解説
PHP AST 徹底解説
do_aki26.4K views
Kanazawa.js.Next by dynamis
Kanazawa.js.NextKanazawa.js.Next
Kanazawa.js.Next
dynamis 1.6K views
Clojure programming-chapter-2 by Masao Kato
Clojure programming-chapter-2Clojure programming-chapter-2
Clojure programming-chapter-2
Masao Kato1.1K views
Scala2.8への移行 by guest5f4320
Scala2.8への移行Scala2.8への移行
Scala2.8への移行
guest5f4320573 views
Java8から17へ by onozaty
Java8から17へJava8から17へ
Java8から17へ
onozaty729 views
TypeScript 言語処理系ことはじめ by Yu Nobuoka
TypeScript 言語処理系ことはじめTypeScript 言語処理系ことはじめ
TypeScript 言語処理系ことはじめ
Yu Nobuoka3.3K views
第三回ありえる社内勉強会 「いわががのLombok」 by yoshiaki iwanaga
第三回ありえる社内勉強会 「いわががのLombok」第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」
yoshiaki iwanaga14.1K views
PostgreSQL - C言語によるユーザ定義関数の作り方 by Satoshi Nagayasu
PostgreSQL - C言語によるユーザ定義関数の作り方PostgreSQL - C言語によるユーザ定義関数の作り方
PostgreSQL - C言語によるユーザ定義関数の作り方
Satoshi Nagayasu11.5K views
GNU awk (gawk) を用いた Apache ログ解析方法 by 博文 斉藤
GNU awk (gawk) を用いた Apache ログ解析方法GNU awk (gawk) を用いた Apache ログ解析方法
GNU awk (gawk) を用いた Apache ログ解析方法
博文 斉藤6.6K views
Androsia:一歩先のメモリ内Androidアプリケーションデータの保護 by サミット・アンワル by CODE BLUE
Androsia:一歩先のメモリ内Androidアプリケーションデータの保護 by サミット・アンワルAndrosia:一歩先のメモリ内Androidアプリケーションデータの保護 by サミット・アンワル
Androsia:一歩先のメモリ内Androidアプリケーションデータの保護 by サミット・アンワル
CODE BLUE695 views
BOF1-Scala02.pdf by Hiroshi Ono
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdf
Hiroshi Ono485 views
BOF1-Scala02.pdf by Hiroshi Ono
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdf
Hiroshi Ono858 views
プログラミング言語Scala by TanUkkii
プログラミング言語Scalaプログラミング言語Scala
プログラミング言語Scala
TanUkkii1.1K views

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