ES2015 [6th edition] で let
と const
が導入された。var
と書いてあるところにはこれらも書ける。
JavaScript の for
は、次の2つの書き方がある。C/C++風の書き方と、in
/of
演算子を使った書き方。
コンテナの要素を単純に使いたいときは後者を使う。
for (式1; 式2; 式3) ... for (var宣言; 式2; 式3) ...
for (要素 in コンテナ) ... for (要素 of コンテナ) ...
for
文1.変数の代入, 2.ループするかどうかの条件式, 3.変数の更新, の3つの引数を取る。2番目の条件式が真の間、ループされる。
下, 2番目の例のように, var
宣言で関数スコープ (forブロックではない) の変数を宣言できる。現代は let
を使うのが通常.
ES5 (2009年) にも for-in文があった。ES2015 (ES6) で, for-in文に加えて for-of文が導入された。書き方は非常に似ている。
in
はキーワードだが, of
はそうではない。文脈依存キーワードになっている。
for ( 左辺値in
式 ) 文 for (var
ForBindingin
式 ) 文 for ( ForDeclarationin
式 ) 文
for ( 左辺値of
AssignmentExpression ) 文 for (var
ForBindingof
AssignmentExpression ) 文 for ( ForDeclarationof
AssignmentExpression ) 文
for-in文は、オブジェクトの全てのプロパティのうち [[Enumerable]] = true
属性を持つものを順に変数に代入し、それで文を実行する。
順序が先頭からとは限らない。余計なものが付く、という難点があり、実用的でない。次の例は配列だが、配列の要素ではなくインデックスになっているし、fn
も渡されている。
in
の後ろにオブジェクトを書いた場合は、key が順番に渡されてくる。
いずれにしても、新しいプログラムを書く際は, もはや for-in文は使うべきではない。
for-of文は, for文に渡されたオブジェクトが「反復可能 (iterable) オブジェクト」であるとき, そのオブジェクトの @@iterator
プロパティを呼び出してイテレータ (後述) を得て, そのイテレータでループを回す。逆に, @@iterator
プロパティを持つオブジェクトが iterable である。
配列 Array
の場合は、ちゃんと配列の要素が順番に得られる。文字列 String
だとそれぞれの code point. Map
だと entries()
の各要素, Set
だと values()
の各要素.
ただのハッシュオブジェクトだと、イテレータがないので, TypeError
例外になる。
新しいプログラムでは, for-of文のほうを使うようにすればいい。
配列を取りそうな場所は、配列決め打ちではなく, iterable オブジェクトであれば受け付けるようにすると汎用性が上がる。
イテレータを生成できるオブジェクトを iterable オブジェクトと呼ぶ。
イテレータは少なくとも next
プロパティとして関数を持たなければならない。return
プロパティ (関数), throw
プロパティ (関数) を持ってもよい。next()
が返すオブジェクトは done
, value
のプロパティを持たなければならないき。
自分でイテレータを作るには、次のようにする;
上の例では iterator を obj
とは別のオブジェクトにしたが、obj
のプロパティとして next
を定義すれば、iterable オブジェクトかつ iterator にすることもできる。