はじめに
以前投稿したものを誤って削除してしまったので再掲載します。せっかくストックしていただいていたのに申し訳ありません。
山田祥寛さんの速習ECMAScript6: 次世代の標準JavaScriptを今すぐマスター! [Kindle版] を読んだので気になった点をまとめたノートです。
あまり詳しい説明はないですし、肝心のモジュールやクラスなど、完全に説明していないものも多くあります。こんな内容が書いてあるんだ程度に見ていただければと思います。回し者ではないですが、書籍は250円と激安なのでおすすめです。
let
変数をブロック {}
スコープに閉じ込める宣言。従来は即時関数を使って変数スコープを関数内に閉じ込めていたが、letを使用する場合単に次のようにすればいい。
var foo = 'foo';
{ // このfooは外のfooとはスコープが違う
let foo = 100;
}
const
オブジェクトに再代入出来ないようにする。代入されているオブジェクトの変更はできる。
// これはエラー
const foo = 100;
foo = 'foo' // error
// 配列は各オブジェクトへのリンクを保持しているだけなので、
// リンク先のオブジェクトへの変更はエラーにならない。
const arr = [1, 2, 3];
arr[1] = 10
整数リテラル(2進数/8進数)
0o<数字>
(ゼロ・オー)で8進数、 0b<数字>
で2進数を表す。ちなみに10進数 -> 各進数への変換は10進数の数字を変換先進数で割って行き、余りを古いものから並べて得られる。 Number.toString()
, Number()
は2/8進数を解釈できるが、 Number.parseInt()
は8進数に対応していないので注意。間違えやすいので数値のパースは Number()
で統一するべき。
0o10 === 8; // true
展開演算子 ...
配列などの列挙可能なオブジェクトを個々の引数に展開してくれる演算子
function foo(arg1, arg2, arg3) {}
foo(...[1, 2, 3]);
可変長引数(Rest parameter) ...
可変の引数を取れるようになる演算子。展開演算子と同じだが関数の引数に適用する。
可変長引数は配列として渡される。この他にもう一つ、後述の分割代入するときも同じ演算子を使う。
funcition foo(...args) {
for (let val of args) { // argsは配列
console.log(val);
}
}
for of 文
for in文と違い、arrayだけでなく列挙可能なarrayライクなオブジェクトであればなんでもいける。またfor inがインデックスを列挙するのに対して、for ofは値を列挙する。さらにfor ofは自分のメンバーだけ列挙し、prototypeのメンバーまで列挙しない。
テンプレート文字列
` は @ キーの方なので注意。
var name = 'john';
console.log(`hello ${name}`); // hello john
関数にテンプレート文字列を渡した場合は第一引数に文字列の配列、第二引数に代入されている変数の配列がそれぞれ渡される。
function foo (formats, ...args) {
console.log(formats); // ["こんにちは", "さん。"]
console.log(args); // ["山田"]
return formats[0] + args[0] + formats[1] // "こんにちは山田さん。"
}
var name = "山田"
foo( `こんにちは${name}さん。` );
Symbol型オブジェクト
symbol型の特徴
- 値が同じシンボルを作成しても同じシンボルはできない = 比較演算子(===)でfalseになる
- 文字列/数値型への暗黙的な変換はできないが、オブジェクト型/ブーリアン型への暗黙変換はできる。
次のように定数の値に使用したりする。
// うっかり同じ値の定数を作っても・・・
const JAVASCRIPT = Symbol(0); // 本来は引数なしSymbol()で作ると良い。
const PHP = Symbol(0);
JAVASCRIPT === PHP // false
分割代入(destructuring)
// 変数fooとbarがまとめて定義、代入される
var [foo, bar] = [1, 2]; // var foo = 1, bar = 2 と同じ
console.log(foo); // 1
console.log(bar); // 2
// ...代入先変数に演算子をつけて配列として代入
var [a, b, ...arr] = [1, 2, 3, 4, 5]; // var a = 1, b = 2, arr = [3, 4, 5] と同じ
値の一部だけを代入する。
正規表現のフィルタ後の返り値を受け取る時などに便利(RegExp.exec()は返り値の最初の配列に引数の文字列全体を返す)
var [, foo, bar] = [10, 20, 30]; // 最初の10は何にも代入されず破棄される
オブジェクトのプロパティに代入
var { foo, bar } = { foo: 'foo!', bar: 'bar!' }; // var foo = 'foo!', bar = 'bar!' と同じ
var data = { fuga: 'fuga!', hoge: { piyo: 'piyo!', goo: 'goo!' } };
var {fuga, hoge, hoge: { piyo, goo } } = data;
// booの値はxに代入される
var { boo: x, woo } = { boo: 'boo!', woo: 'woo!' };
// デフォルト値を設定
var { bow = 'bow!', wow } = { wow: 'wow!' };
宣言と代入を分ける
// 変数を宣言してから代入する場合は、オブジェクトの場合全体を 括弧 () で囲む
var cup, tea;
({ cup, tea } = { cup: 'japan', tea: 'green tea' });
使い所: 変数の値を入れ替える
var foo = 1, bar = 2;
[ foo, bar ] = [ bar, foo ];
使い所: 関数の引数にオブジェクトを渡す -> 関数内部でただの変数として扱う
function foo ({ data1, data2, data3 }) {
// 従来はdata.data1などとしなければいけなかった
return data1 + data2 + data3;
}
// 関数を介して { data1, data2, data3 } = {data1: 10, data2: 20, data3: 30}
// を行っている(左辺が関数側、右辺が呼び出し側)。
foo({ data1: 10, data2: 20, data3: 30 });
使い所: 関数の返り値を選択的に取得
function getInfo({id}) {
return ['id'];
}
var book = {
id: '1234', title: 'awesome', price: 2000
};
// 関数を介して { id } = { id: '1234', title: 'awesome', price: 2000 }
// を行っている
getInfo(book); // "1234"
アロー関数でオブジェクトリテラルを返すとき
()で囲ってやる。括弧なしだとラベルとみなされてしまう。
foo = () => ({ foo: 'foo!' });
Promiseオブジェクト
jqueryのと同じ。
function foo(val) {
return new Promise((resolve, reject) =>
setTimeout(() => {
if (val) {
resolve(true);
} else {
reject(false);
}
}, 2000)
)
}
foo(true).then(
response => console.log(response),
error => console.log(error)
);
Promise.allは配列として渡したコールバックすべてが完了した時点でresolve/error関数を実行する。
どれか一つでも失敗した場合はerror関数が実行される。
Promise.all([
foo('foo!'),
foo('bar!'),
foo('bow!')
]).then(...);
Promise.raceは配列として渡したコールバックの最初の一つが完了した時点で(以下略)。
resolve/error関数は完了した最初の一つの結果だけを見て実行される。
Promise.rece([
foo('foo!'),
foo('bar!'),
foo('bow!')
]).then(...);
Proxyコンストラクタ
obj <- new Proxy(obj, handler) <- <Developer>
という構図で使われる。
ハンドラーはトラップとも呼ばれ、set, getなどを指定できる。トラップの詳しくはMDNかkindleテキストを参照。
Proxyはあくまでobjのプロキシなので、Proxyオブジェクトに加えた変更は本体のobjにも反映されることに注意。
Map
mapはキーと値のセットでデータを管理するためのオブジェクト。従来はオブジェクトリテラレルでキーと値を管理していたが、オブジェクトはキーに文字列しか取れない、lengthメソッドが使えないなどの制約があった。
mapは、
- 任意の型でキーを設定できる。
- mapのサイズをlengthプロパティで取得できる。
- 余分なデフォルトキーを持たないクリーンなmapを作成できる。
mapは get
, set
, values
, keys
, has
などのメソッドを持つ。
詳しくはkindleテキストを参照。
変数を同名のプロパティに設定する
var foo = 'foo!', bar = 'bar!';
// 従来は { foo: foo, bar: bar } とする必要があった。
var obj = { foo, bar };
メソッド定義時に function 表記が省略可能
function foo() {
bar() {
//...
}
}
ジェネレーター
yieldはreturnと同様、値を呼び出し元に返すが、returnが関数の実行を終了する(=実行の度に初期化される)のに対してyieldは処理を中断する。
つまり再度呼び出すまで状態が保存される。
function* foo(num) {
while (num >= 0) {
yield num--;
}
}
foo(5); // 5, 4, 3, 2, 1