SlideShare ist ein Scribd-Unternehmen logo
1 von 85
Downloaden Sie, um offline zu lesen
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

Weitere ähnliche Inhalte

Was ist angesagt?

Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料時響 逢坂
 
Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料時響 逢坂
 
Scala の関数型プログラミングを支える技術
Scala の関数型プログラミングを支える技術Scala の関数型プログラミングを支える技術
Scala の関数型プログラミングを支える技術Naoki Aoyama
 
初めてのHaskell (表)
初めてのHaskell (表)初めてのHaskell (表)
初めてのHaskell (表)karky7
 
Java Puzzlers JJUG CCC 2016
Java Puzzlers JJUG CCC 2016Java Puzzlers JJUG CCC 2016
Java Puzzlers JJUG CCC 2016Yoshio Terada
 
Java SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイルJava SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイルなおき きしだ
 
ジェネリクスの基礎と クラス設計への応用
ジェネリクスの基礎とクラス設計への応用ジェネリクスの基礎とクラス設計への応用
ジェネリクスの基礎と クラス設計への応用nagise
 
Van laarhoven lens
Van laarhoven lensVan laarhoven lens
Van laarhoven lensNaoki Aoyama
 
言語処理系入門€5
言語処理系入門€5言語処理系入門€5
言語処理系入門€5Kenta Hattori
 
JavaのGenericsとは?
JavaのGenericsとは?JavaのGenericsとは?
JavaのGenericsとは?Kenji Nakamura
 
C++ マルチスレッドプログラミング
C++ マルチスレッドプログラミングC++ マルチスレッドプログラミング
C++ マルチスレッドプログラミングKohsuke Yuasa
 
Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3Ransui Iso
 
冬のLock free祭り safe
冬のLock free祭り safe冬のLock free祭り safe
冬のLock free祭り safeKumazaki Hiroki
 
Metaprogramming in JuliaLang
Metaprogramming in JuliaLangMetaprogramming in JuliaLang
Metaprogramming in JuliaLangYuichi Motoyama
 
ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2
ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2
ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2Masatoshi Tada
 
【java8 勉強会】 怖くない!ラムダ式, Stream API
【java8 勉強会】 怖くない!ラムダ式, Stream API【java8 勉強会】 怖くない!ラムダ式, Stream API
【java8 勉強会】 怖くない!ラムダ式, Stream APIdcomsolution
 
「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」
「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」
「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」Nagi Teramo
 

Was ist angesagt? (20)

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

Andere mochten auch

FileReader and canvas and server silde
FileReader and canvas and server sildeFileReader and canvas and server silde
FileReader and canvas and server sildeNet Kanayan
 
Getting started with ES6 : Future of javascript
Getting started with ES6 : Future of javascriptGetting started with ES6 : Future of javascript
Getting started with ES6 : Future of javascriptMohd Saeed
 
Prototypeベース in JavaScript
Prototypeベース in JavaScriptPrototypeベース in JavaScript
Prototypeベース in JavaScriptRyo Maruyama
 
ES6 はじめました
ES6 はじめましたES6 はじめました
ES6 はじめましたNet Kanayan
 
JavaScript : What is it really? AND Some new features in ES6
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 ES6Aayush Shrestha
 
JavaScript.Next Returns
JavaScript.Next ReturnsJavaScript.Next Returns
JavaScript.Next Returnsdynamis
 
はじめてのWallaby.js
はじめてのWallaby.jsはじめてのWallaby.js
はじめてのWallaby.jsShunta Saito
 
Google App EngineでTwitterアプリを作ろう
Google App EngineでTwitterアプリを作ろうGoogle App EngineでTwitterアプリを作ろう
Google App EngineでTwitterアプリを作ろうkenji4569
 
断言して間違えると信頼度が低下するというベイズの話
断言して間違えると信頼度が低下するというベイズの話断言して間違えると信頼度が低下するというベイズの話
断言して間違えると信頼度が低下するというベイズの話Junya Hayashi
 
アニメーションの実装つらい話
アニメーションの実装つらい話アニメーションの実装つらい話
アニメーションの実装つらい話kata shin
 
Bacon.jsではじめる関数型リアアクティブプログラミング入門 with ES6
Bacon.jsではじめる関数型リアアクティブプログラミング入門 with ES6Bacon.jsではじめる関数型リアアクティブプログラミング入門 with ES6
Bacon.jsではじめる関数型リアアクティブプログラミング入門 with ES6Haraguchi Go
 
これからのJavaScriptの話
これからのJavaScriptの話これからのJavaScriptの話
これからのJavaScriptの話Shogo Sensui
 

Andere mochten auch (20)

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

Ähnlich wie ECMAScript 6 Features(PDF 版)

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

Ähnlich wie ECMAScript 6 Features(PDF 版) (20)

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

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