狠狠撸

狠狠撸Share a Scribd company logo
ECMAScript 6 Features
2015/06/06
2015/06/30 改訂
taskie
1 / 85
このスライドについて
ECMAScript 6 の新機能を紹介するスライドです
仕様書:ECMAScript 2015 Language Speci?cation ? 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 Over?ow
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 ?ag ( 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 以前でもクラスや継承を実現するパターンは存在する
Co?eescriptと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 Re?ect object do in JavaScript? -
Stack Over?ow
66 / 85
Promise
ES6
非同期処理をうまく扱うための仕組み
参考:JavaScript Promiseの本
then のメソッドチェーンで処理順を制御し、 catch でエラー処理をする
非同期処理を行うライブラリを作る際には Promise オブジェクトを返す API
を用意しておくとよい
petkaantonov/bluebird などの poly?ll が存在
67 / 85
Promise
ES6
new Promise((resolve, reject) => {
setTimeout(() => resolve("A"), 1000);
}).then((str) => {
console.log(str); // A
return new Promise((resolve, reject) => {
setTimeout(() => resolve("B"), 1000);
}).then((str) => {
console.log(str); // B
return Promise.reject(new Error("C"));
});
}).catch((err) => {
console.log(err.message); // C
return "D";
}).then((str) => {
console.log(str); // D
});
console.log("Start!");
Start! → A → B → C → D の順に表示される
68 / 85
Symbol
ES6
var sym1 = Symbol("foo");
var sym2 = Symbol("bar");
var sym3 = Symbol("bar");
console.log(sym1 == sym2); // false
console.log(sym2 == sym3); // false
console.log(sym3 == sym1); // false
一意なキーの生成などに利用
参考:Symbolについて - JS.next
69 / 85
Symbol.iterator
ES6
var obj = { };
obj[Symbol.iterator] = function () {
return {
next: function () {
return (this.i < 3) ?
{done: false, value: this.i++} : {done: true};
},
i: 0
}
};
for (var x of obj) console.log(x); // 0 1 2
自前のオブジェクトを for ? of で列挙できる
参考:ES6のイテレータについて調べた - ひよこ3分07秒のTechブログ
70 / 85
ビルトイン拡張 (Built-in
extensions)
Oject.assign
Object.setPrototypeOf
関数名の取得
String
Array
Number
Math
71 / 85
Object.assign
ES6
var obj = {foo: "bar", x: 42};
Object.assign(obj, {foo: "baz"}, {hoge: "piyo"});
console.log(obj); // { "foo" : "baz", "x" : 42 , "hoge" : "piyo" }
オブジェクトのマージ
72 / 85
Object.setPrototypeOf
ES6
var proto = {hoge: "piyo"};
var obj = {foo: "bar"};
Object.setPrototypeOf(obj, proto);
console.log(Object.getPrototypeOf(obj) === proto); // true
console.log(obj.foo); // bar
console.log(obj.hoge); // piyo
obj.hoge = "fuga";
console.log(obj.hoge); // fuga
オブジェクトのプロトタイプを設定する
いわゆる __proto__ の代替として利用可
73 / 85
関数名の取得
ES6
function foo() { }
console.log(foo.name); // foo
var bar = function () { };
console.log(bar.name); // bar
console.log((function () { }).name === "") // true
name プロパティで関数名を取得できる
74 / 85
String
ES6
console.log("? ".codePointAt(0)); // 127843
console.log(String.fromCodePoint(12354, 32, 127843)); // あ ?
console.log("A".repeat(3)); // AAA
console.log("heart".includes("ear")); // true
console.log("heart".startsWith("hear")); // true
console.log("heart".startsWith("ear", 1)); // true
console.log("heart".endsWith("art")); // true
75 / 85
Array
ES6
var obj = {0: "foo", 1: "bar", length: 2};
console.log(Array.from(obj)); // ["foo", "bar"]
function * gen() { yield 2; yield 3; yield 5; }
console.log(Array.from(gen())); // [2, 3, 5]
console.log([2, 3, 5, 7].find(x => x > 3)); // 5
console.log([2, 3, 5, 7].findIndex(x => x > 3)); // 2
console.log(new Array(3).fill(42)); // [42, 42, 42]
from : 「配列のような」オブジェクトを配列に変換
find : 条件に一致する最初の要素を得る
findIndex : 条件に一致する最初の要素の添字を得る
76 / 85
Number
ES6
console.log(Number.isFinite(42)); // true
console.log(Number.isFinite(-Infinity)); // false
console.log(Number.isFinite(NaN)); // false
console.log(Number.isInteger(42.00000)); // true
console.log(Number.isInteger(42.00001)); // false
console.log(Number.isSafeInteger(1e+15)); // true
console.log(Number.isSafeInteger(1e+16)); // false
console.log(Number.EPSILON); // 2.220446049250313e-16
console.log(Number.MIN_SAFE_INTEGER); // -9007199254740991
console.log((Number.MIN_SAFE_INTEGER - 1) | 0); // 0
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
console.log((Number.MAX_SAFE_INTEGER + 1) | 0); // 0
77 / 85
Math
ES6
console.log(Math.sign(-42)); // -1
console.log(Math.cosh(Math.log(2))); // 1.25
console.log(Math.trunc(-3.5)); // -3
console.log(Math.cbrt(27)); // 3
console.log(Math.hypot(3, 4)); // 5
sign : 符号(-1, 0, +1)
cosh , sinh , tanh : 双曲線関数
trunc : 0 方向への丸め
cbrt : 立方根
hypot : 二乗和の平方根
78 / 85
サブクラス化 (Subclassing)
Array , RegExp , Function , Promise , Boolean , Number , String ,
Map , Set を継承したクラスを定義できる
79 / 85
モジュール (Modules)
import , export
80 / 85
import , export
CommonJS
// app.js
var utils = require("./utils");
utils.hello(); // Hello, world!
console.log(utils.answer); // 42
// utils.js
function hello() { console.log("Hello, world!"); }
var answer = 42;
module.exports = { hello: hello, answer: answer };
81 / 85
import , export
ES6
// app.js
import utils from "./utils";
utils.hello(); // Hello, world!
console.log(utils.answer); // 42
// utils.js
function hello() { console.log("Hello, world!"); }
var answer = 42;
export default { hello: hello, answer: answer };
クラスなども export 可能
参考:Babelで理解するEcmaScript6の import / export - Qiita
82 / 85
import * as
ES6
// app.js
import * as utils from "./utils";
utils.hello(); // Hello, world!
console.log(utils.answer); // 42
// utils.js
export function hello() { console.log("Hello, world!"); }
export var answer = 42;
83 / 85
import { ... }
ES6
// app.js
import { hello, answer } from "./utils";
hello(); // Hello, world!
console.log(answer); // 42
// utils.js
export function hello() { console.log("Hello, world!"); }
export var answer = 42;
84 / 85
END
We are hiring!
http://unipro.co.jp/
85 / 85

More Related Content

ECMAScript 6 Features(PDF 版)

  • 2. このスライドについて ECMAScript 6 の新機能を紹介するスライドです 仕様書:ECMAScript 2015 Language Speci?cation ? 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 Over?ow 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 ?ag ( 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 以前でもクラスや継承を実現するパターンは存在する Co?eescriptと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 Re?ect object do in JavaScript? - Stack Over?ow 66 / 85
  • 67. Promise ES6 非同期処理をうまく扱うための仕組み 参考:JavaScript Promiseの本 then のメソッドチェーンで処理順を制御し、 catch でエラー処理をする 非同期処理を行うライブラリを作る際には Promise オブジェクトを返す API を用意しておくとよい petkaantonov/bluebird などの poly?ll が存在 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