配列のループ処理に使用する、for..in,for...ofの違いについて調べてみました。
1.for..in,for...ofの違い
何を対象にループ処理を行っているかに違いがあります。
|
for..in |
for..of |
ループ対象 |
列挙可能なプロパティ |
反復可能なオブジェクトの値 |
※for...inは現在はあまり使用しません。 詳細は「4.まとめ」参照
2.for..inについて
for..inとは
オブジェクトのすべての列挙可能なプロパティに対して、順序不定で繰り返し処理を行います。
■Array でのループ処理
for (let v in [1,2,3]) console.log(v);
■Stringでのループ処理
for (const v in "abc") console.log(v);
■連想配列(Object)でのループ処理
for (let v in {a:1,b:2}) console.log(v);
■連想配列(Map)でのループ処理
var m = new Map([['a',1],['b',2]]);
for (let v in m) console.log(v);
■Setでのループ処理
var s = new Set([1,2,3]);
for (let v in s) console.log(v);
for..inの注意点
注意1:実行順を指定できない
for...in ループは、任意の順序でオブジェクトのプロパティに対して反復します (なぜ繰り返しの見かけの順序に依存できないのかについては、詳細は delete オペレーターを参照)。
実行順を指定する場合は、数値のインデックスでの for ループ (か Array.prototype.forEach() か for...of ループ) を使いましょう。
注意2:継承したプロパティもループ対象となってしまう
「Object」や「Array」に設定したカスタムプロパティも、
ループ処理の対象となってしまいます。
Object.prototype.objCustom = function () {};
Array.prototype.arrCustom = function () {};
const fruits = ["リンゴ", "ミカン", "バナナ"];
for (const key in fruits) {
console.log(key);
}
継承したプロパティは「hasOwnProperty()」で除外できます。
for (const key in fruits) {
if (fruits.hasOwnProperty(key)) {
console.log(key);
}
}
3.for..ofについて
for..ofとは
反復可能なオブジェクトが定義した順序で値を反復処理します。
■Array でのループ処理
for (let v of [1,2,3]) console.log(v);
■Stringでのループ処理
for (let v of "abc") console.log(v);
■連想配列(Object)でのループ処理
for (let v of {a:1,b:2}) console.log(v);
■連想配列(Map)でのループ処理
var m = new Map([['a',1],['b',2]]);
for (let v of m) console.log(v);
■Setでのループ処理
var s = new Set([1,2,3]);
for (let v of s) console.log(v);
4.まとめ
for...inは、ECMAScript2015でMap(連想配列)が追加される以前、Objectを連想配列として使用していた時のコードとの互換性のために残っている機能のため、現在はあまり使用しません。
配列の操作は、for...of (あるいは forEach, map, reduce, some, every, find, find_index, filter メソッド)を使用しましょう。
※余談
for文内の変数宣言「for (const key in fruits)」が、letではなくconstでよいという点については関数のスコープが関係しています。
let と const について >> ループと反復処理 · Issue #567 · asciidwango/js-primer · GitHub
参考リンク
【備忘録】配列におけるfor in と for of の違い - Qiita
for...in - JavaScript | MDN
for...of - JavaScript | MDN