現代的JavaScriptおれおれアドベントカレンダー2017 – 22日目
概要
配列とか Map とかは for-of 文を使って、添え字アクセス? [] を使わずにぐるぐるできます。
const arr = ['Hello', 'World', '!'];
for (let item of arr) {
console.log(item);
}
普通のオブジェクトでは使えないけど、インターフェイスを追加すれば使えるようにもなります。
使い方
普通の for 文を使って配列で arr[i] する代わりに for-of でいきなり値を取ってこれます。
const arr = ['Hello', 'World', '!'];
for (let item of arr) {
console.log(item);
}
配列以外でも反復可能なオブジェクト(後述)で使えます。
const map = new Map([[1, 11], [2, 22], [3, 33]]);
for (let [key, value] of map) {
console.log(`${key}: ${value}`);
}
文字列と絵文字
文字列でも使えます。絵文字とかのサロゲートペアを上手に扱ってくれます。やったね。
const str = '#sushi🍣';
console.log('--- for ---');
for (let i = 0; i < str.length; i++) {
console.log(str[i]);
}
console.log('--- for-of ---');
for (let item of str) {
console.log(item);
}
--- for ---
#
s
u
s
h
i
�
�
--- for-of ---
#
s
u
s
h
i
🍣
反復可能なオブジェクト
for-of 文は反復可能なオブジェクトに対して利用することができます。
対応してないオブジェクトだとエラーに。
const obj = {};
for (let item of obj) { // TypeError: obj[Symbol.iterator] is not a function
console.log(item);
}
反復可能なオブジェクト
この「反復可能なオブジェクト (iterable object)」とは、「イテレータ」を作成するインターフェイスを整えたオブジェクトのことです。配列 Array や Map 等が該当します。
インターフェイスが整っていれば何でも良いので、自作することもできます。
// 反復可能なオブジェクト
const iterable = {
// for-ofに必要なインターフェイス
[Symbol.iterator]() {
const max = 10;
let n = 0;
const iterator = {
next() {
return { value: n++, done: n > max };
},
};
return iterator;
},
};
// よっしゃー使うぞー
for (let item of iterable) {
console.log(item);
}
詳細は別稿参照。
その他
for-in と for-of
もちろん別物なんだけど、同じ項 (13.7.5) でまとめて定義されてるので、兄弟みたいなものらしい。
for-in はカンマ , 区切りの値を置ける
なんでOKなんだろ。
const arr1 = [100];
const arr2 = [200];
arr1.foo = 123;
arr2.bar = 123;
for (let index in arr1, arr2) {
console.log(index);
}
もちろん末尾のもの arr2 が有効になります。
0
bar
for-of でやると構文エラーです。
const arr1 = [100];
const arr2 = [200];
for (let item of arr1, arr2) { // SyntaxError: Unexpected token ,
console.log(item);
}
for-in で初期値を書ける場面が
"use strict" の厳格モードでない場面で、 var をここで使用する場合のみ、初期値を置ける。 let を使ったり、別の場所で var 宣言してからの代入だとだめ。
const arr = [1, 2, 3];
for (var index = 'wow' in arr) {
console.log(index);
}
といってもその初期値が適用される場面てあるんだろか。
謎仕様だなー。後方互換のためなのかな。
参考
- ECMAScript® 2017 Language Specification
- 13.7.5 The for-in and for-of Statements
- 13.7.5.12 Runtime Semantics: ForIn/OfHeadEvaluation ( TDZnames, expr, iterationKind ) … イテレータの作成。初期処理的な
- 13.7.5.13 Runtime Semantics: ForIn/OfBodyEvaluation ( lhs, stmt, iterator, iterationKind, lhsKind, labelSet ) … イテレータを使って反復処理する
- 13.7.5.15 EnumerateObjectProperties ( O ) …
for-in用のイテレータ - 6.1.5.1 Well-Known Symbols …
Symbole.iterator - 7.4.1 GetIterator ( obj [ , method ] )
- 7.4.5 IteratorStep ( iterator ) … イテレータで反復
- 25.1 Iteration
- B.3.6 Initializers in ForIn Statement Heads …
for-inで初期値使える
- for…of – JavaScript | MDN
- for…in – JavaScript | MDN