現代的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