今更 ES2015 まとめた
今更 ES2015 まとめた
この記事を整形しただけです
ES2015について (ES6) · takahashiakira/tech_for_web Wiki · GitHub)
Class
ES5 における prototype 構文にあたる
class Greet { constructor(name) { // プロパティ this.name = name; } // インスタンスメソッド hello() { console.log('Hello, My name is ' + this.name) } // スタティックメソッド static create(name) { return new Person(name); } } var tom = new Greet('Tom'); // インスタンスメソッドの実行 tom.hello(); // スタティックメソッドの呼び出し var john = Greet.create("John");
let
ブロックスコープ内のみで利用可能な変数定義。
var foo = 'foo'; { // この foo は外の foo とはスコープが違うので別物 let foo = 100; }
let の宣言をブロックで囲めば、即時関数の中で private な変数を宣言する必要がなくなる
(function () { // private var food = 'Meow Mix'; }()); console.log(food); // Reference Error
{ // private let food = 'Meow Mix'; } console.log(food); // Reference Error
const
定数のため再代入できない
const foo = 100; foo = 'foo' // error
配列は各要素のアドレスを保持しているだけなので、要素の値変更はエラーにならない
const arr = [1, 2, 3]; arr[1] = 10
Arrow Function
// ES5 var func = function (x, y) { return x + y; }
// ES6 var func = (x, y) => { return x + y; }
bind
bind は this の指す先を明示的に指定したオブジェクトに変更できるもので、イベントリスナーなどで this の中身が変わってしまう場合などに役に立つ。アロー関数内では this の値をバインドしなくても利用できる
// ES5 function Person(name) { this.name = name; } Person.prototype.prefixName = function (arr) { return arr.map(function (character) { return this.name + character; }.bind(this)); // bind しないと this.name が使えない };
// ES6 function Person(name) { this.name = name; } Person.prototype.prefixName = function (arr) { // this.name をいきなり使える return arr.map(character => this.name + character); };
Method
ハッシュ内のメソッドの function も省略できるようになった
// ES5 var counter = { count: 0, // メソッド increment: function () { this.count++; } }
// ES6 var counter = { count: 0, // メソッド increment() { this.count++; } }
Parameter
Rest Parameter
引数を可変長で利用できる
function rest (...rest){ console.log(rest); } // 好きなだけ引数を渡せる rest(1, 2, 3); // [10, 20 ,30]
Default Parameter
関数でデフォルトパラメータを指定できる
function add (a = 1, b = 2){ return a + b; }
Template Strings
テンプレートリテラル を利用して特殊文字をエスケープする必要がなくなった
JavaScript の テンプレートリテラル を極める!
// バッククオート (`) で囲めば、ちゃんと " はエスケープされる let text = `This string contains "double quotes" which are escaped.`;
var name = 'Bob'; // 文字列に変数を埋め込めるようになった console.log('Hello, ${name}.');
// 改行に改行コードを使う必要がなくなった let text = ( `cat dog nickelodeon` );
let today = new Date(); // 式も文字列内で展開して扱えるようになった let text = `The time and date is ${today.toLocaleString()}`;
Map
key-value データを扱うクラスである Map を利用できるようになった
var map = new Map(); map.set('key1', 'value1'); map.get('key1'); // "value1" map.has('key1'); // true map.delete('key1');
var map = new Map([['k1', 'v1'], ['k2', 'v2']]); map.get('k1') // "v1" console.log(map2.size); // 2 map2.clear(); // 全データのクリア
WeakMap
WeakMap は、Key に指定されたオブジェクトに対して弱い参照を持つことでガベージコレクションを妨げないクラスとなっている。そのため繰り返しを伴うメソッドや clear メソッドは存在しないが、キャッシュに利用したり、プライベートプロパティとして利用できる
const privateNames = new WeakMap(); class Foo { constructor(name) { // name をプライベートプロパティとして保持 privateNames.set(this, name); } getName() { return privateNames.get(this); } }
Symbol
オブジェクトプロパティのキーとして使うことができるユニークな値を生成。プロパティ名がコンフリクトしないことを保証できるため、文字通りシンボルとして使われるイベント名などの定数や列挙型の値として使うと便利
var syml = Symbol(); var syml2 = Symbol('foo'); syml2.toString(); // "Symbol("foo")" console.log(syml2 === Symbol('foo')); // false var obj = {[syml2]: 1}; Object.keys(obj); // [] Object.getOwnPropertySymbols(obj); // [Symbol(foo)]
var obj = { [Symbok.toStringTag]: 'Foo!' } console.log(String(obj)); // "[object Foo!]"
Object.assign(target, source1, source2...)
オブジェクトをターゲットにシャローコピーする。jQuery の $.extend と同様の機能。
var objA = { "key1": 1, } var objB = { "key1": 2, "key2": 2 } // ObjA に objB の要素を上書きコピーする var objC = Object.assign(objA, objB); console.log(objA == objC); // true console.log(objA["key1"] == 2); // true console.log(objA["key2"] == 2); // true
String
String.includes(string)
文字列の中に引数の文字列が含まれているか真偽値を返す
const string = 'food'; const substring = 'foo'; console.log(string.includes(substring)); // true
String.repeat(n)
文字列を n 回繰り返す
'meow'.repeat(3); // 'meowmeowmeow'
Array
- Array.from: Array のようなオブジェクトやイテレータを Array に変換
- Array.of: 引数を要素に持つ配列を生成する
var arr = Array.from('foo'); console.log(arr); // ['f', 'o', 'o']
var arr = MyArray.of[1, 2, 3]; console.log(arr); // [1, 2, 3] console.log(arr instanceof MyArray); // true
イテレータへの対応として、Map や Set と互換性のあるメソッド keys, values, entries が追加された。その他、配列内で要素をコピーするメソッド copyWithin や、要素を指定の値で埋めるメソッド fill や、find、findIndex が追加された
Promise
非同期処理を抽象化する統一的なインターフェース
// 非同期処理 function wait(time){ // 引数名は自由 return new Promise((resolve, reject) => { setTimeout(() => { // 処理が成功の場合、resolve の引数の中で then に渡される戻り値を書く resolve('wait: ' + time); }, time); }); } // then 以下に resolove 時の処理。value で戻り値を受け取る wait(2000).then(value => { console.log(value); // "wait: 2000" // then をメソッドチェーンにすることもできる }).then(value => { conosle.log(value); // undefined });
Promiseのエラー処理
// 非同期処理 function getUrl(url) { return new Promise((resolve, reject) => { var xhr = new XMLHttpRequest(); xhr.open('GET', url); xhr.onload = () => { if (xhr.status == 200) { resolve(xhr.statusText); } else { // 処理が失敗の場合、reject の引数の中で catch に渡される戻り値を書く reject(new Error(xhr.statusText)); } } xhr.onerror = () => { // 処理が失敗の場合、reject の引数の中で catch に渡される戻り値を書く reject(new Error(xhr, statusText)); }; xhr.send(); }); } getUrl('/items').then(res => { var items = JSON.parse(res); someProcess(items); // catch 以下に reject 時の処理。e で戻り値を受け取る }.catch(e => { console.error(e); });
Promise.all
全ての非同期処理が終わるまで待つ
Promise.all([ // 配列の中で非同期処理を複数実行 getUrl('/foo'), getUrl('/bar') ]).then(res => { // 受け取る戻り値 res も配列 console.log(res[0]); console.log(res[1]); }).catch(e => { console.error(e); });
co
Generator をベースにしたライブラリ。yield の処理が終わるまで次に進まない。非同期処理の可読性があがる
// ジェネレーター関数で非同期処理を実装 function * getFirstitem() { var Items = yield getUrl('/items'); var item = yield getUrl('items/' + imtes[0].id); return item; } var co = require('co'); co(function* () { // try - catch 文 try { var item = yield getFirstItem(); // ジェネレータ関数を同期処理として実行 someProcess(item); // item の取得を待ってから実行される } catch(e) { console.error(e); } });
Generator
処理を停止したり再開したりできる特殊な関数。yield で処理が一旦止まるので、next で次に進める
function* 宣言 (末尾にアスタリスクが付いた function キーワード)
Generator オブジェクトを返すジェネレーター関数を定義
function generator() { yield 1; yield 2; return 3; } var g = generator(); // generator1 の処理が全部終わったかどうかは done でわかる conosle.log(g.next()); // {value: 1, done: false} conosle.log(g.next()); // {value: 2, done: false} conosle.log(g.next()); // {value: 3, done: true} for (let n of generator()) { console.log(n); }
非同期処理との組み合わせ
// 非同期処理 asyncflow(function * () { var items = yield getUrl('/items'); var id = items[0].id; var item = yield.getUrl('/items/', + id); console.log(item); }); function asyncflow(generator){ var g = generator(); var next = value => { var result = g.next(value); if (!result.done) { promise = result.value; promise.then(value => { next(value); }); } }; next(); }
import/export
ES2015 では Webpack などのライブラリを使わなくても AMD や CommonJS の記法を扱うことができる
エクスポート
default export
let foo = "foo!"; export default foo; class Baz { constructor() { console.log('Baz!'); } } export default Baz;
インポート
import from
import foo from './foo'; import Baz from './baz';
as
名前を変更できる
import {foo as bar} from './foo';
*
全てをインポートできる
import * as util from 'math/addition';
デフォルトのオブジェクトから、どの機能をインポートするか選択する
import React, { Component, PropTypes } from 'react';