web-dev-qa-db-ja.com

JavaScriptのステートメント(for ... in)とステートメント(for ... of)の違いは何ですか?

私はfor... inループ(それはキーを繰り返し処理する)が何であるかを知っていますが、for... of(それは値を繰り返し処理する)について初めて聞いたことがあります。私はfor... ofループと混同しています。私は夢中になりませんでした。これは以下のコードです:

var arr = [3, 5, 7];
arr.foo = "hello";

for (var i in arr) {
   console.log(i); // logs "0", "1", "2", "foo"
}

for (var i of arr) {
   console.log(i); // logs "3", "5", "7"
    //it is does not log "3", "5", "7","hello"
}

for... ofはプロパティ値を反復処理します。それならなぜそれは"3", "5", "7","hello"の代わりに"3", "5", "7"を記録しない(返す)のでしょうか?しかしfor... inループは各キー( "0"、 "1"、 "2"、 "foo")を反復処理します。ここでfor... inループもfooキーを繰り返します。しかし、... fooプロパティの値、すなわち"hello"の値を反復しないのは...なぜそれがそのようなのでしょうか。

簡単に言えば、長い話:

ここで私はコンソールfor... ofループです。それはlog "3", "5", "7","hello"であるべきですが、ここでそれは"3", "5", "7"を記録します。どうして ?

リンク例

289
Mukund Kumar

for in は、オブジェクトの列挙可能なプロパティ名をループ処理します。

for of (ES6の新機能)は オブジェクト固有の イテレータ を使用し、それによって生成された値をループ処理します。

あなたの例では、 配列イテレータ は、(インデックスでないプロパティを無視して)配列内のすべての値を返します。

216
Bergi

私は完全な答えを見つけます。 https://www.typescriptlang.org/docs/handbook/iterators-and-generators.html

for..offor..inの両方のステートメントはリストを反復します。反復される値は異なりますが、for..inは反復されるオブジェクトのキーのリストを返し、for..ofは反復されるオブジェクトの数値プロパティの値のリストを返します。

これがこの違いを示す例です。

let list = [4, 5, 6];

for (let i in list) {
   console.log(i); // "0", "1", "2",
}

for (let i of list) {
   console.log(i); // "4", "5", "6"
}

もう1つの違いは、for..inが任意のオブジェクトに対して作用することです。これは、このオブジェクトのプロパティを調べる方法として機能します。一方、for..ofは主に反復可能オブジェクトの値に関心があります。 MapやSet implement Symbol.iteratorプロパティのような組み込みオブジェクトは保存された値へのアクセスを許可します。

let pets = new Set(["Cat", "Dog", "Hamster"]);
pets["species"] = "mammals";

for (let pet in pets) {
   console.log(pet); // "species"
}

for (let pet of pets) {
    console.log(pet); // "Cat", "Dog", "Hamster"
}
177
Alireza Fattahi

For ... forループ

for ... in ループは、カウントロジックと終了条件を排除することによってforループの弱点を改善します。

例:

const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

for (const index in digits) {
  console.log(digits[index]);
}

しかし、それでも配列の値にアクセスするためにインデックスを使用するという問題に対処する必要があります。以前よりも混乱を招きます。

また、for ... inループを使用すると、配列(または別のオブジェクト)にメソッドを追加する必要があるときに、大きな問題が発生する可能性があります。 for ... inループは列挙可能なすべてのプロパティをループ処理するため、配列のプロトタイプにプロパティを追加すると、それらのプロパティもループに表示されます。

Array.prototype.decimalfy = function() {
  for (let i = 0; i < this.length; i++) {
    this[i] = this[i].toFixed(2);
  }
};

const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

for (const index in digits) {
  console.log(digits[index]);
}

プリント:

1

2

3

4

5

6

7

8

9

function(){for(let i = 0; i <this.length; i ++){this [i] = this [i] .toFixed(2); }}

そのため、for ... inループは配列をループするときに推奨されません。

_ note _ forEachループ は、JavaScriptのforループの一種です。ただし、 forEach() は実際には配列メソッドなので、配列でのみ使用できます。 forEachループを停止または中断する方法もありません。ループでそのような動作が必要な場合は、基本的なforループを使用する必要があります。

ループの〜について

for ... of loopは、反復可能なあらゆるタイプのデータをループ処理するために使用されます。

例:

const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

for (const digit of digits) {
  console.log(digit);
}

プリント:

1

2

3

4

5

6

7

8

9

これはfor ... ofループをすべてのforループの中で最も簡潔なバージョンにします。

しかし、もっと待ってください。 for ... ofループには、forおよびfor ... inループの弱点を修正するいくつかの追加の利点もあります。

For ... ofループはいつでも停止または中断できます。

const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

for (const digit of digits) {
  if (digit % 2 === 0) {
    continue;
  }
  console.log(digit);
}

プリント:

1

3

5

7

9

オブジェクトに新しいプロパティを追加することを心配する必要はありません。 for ... ofループは、オブジェクト内の値だけをループします。

32
Elar

For-inステートメントは、オブジェクトの列挙可能なプロパティを任意の順序で繰り返します。

ループは、オブジェクト自体の列挙可能なすべてのプロパティと、オブジェクトがそのコンストラクタのプロトタイプから継承するものを繰り返し処理します。

あなたはそれを "for in"が基本的に反復して全てのキーをリストアップすると考えることができます。

var str = 'abc';
var arrForOf = [];
var arrForIn = [];

for(value of str){
  arrForOf.Push(value);
}

for(value in str){
  arrForIn.Push(value);
}

console.log(arrForOf); 
// ["a", "b", "c"]
console.log(arrForIn); 
// ["0", "1", "2", "formatUnicorn", "truncate", "splitOnLast", "contains"]
7
Devdutta Natu

違いfor..infor..of

for..infor..ofはどちらも、データ構造を反復処理するために使用されるループ構造です。唯一の違いはそれらが繰り返すものにあります:

  1. for..inは、オブジェクトのすべての列挙可能な プロパティキー を反復処理します。
  2. for..ofは、反復可能オブジェクトの values を反復処理します。反復可能オブジェクトの例は、配列、文​​字列、およびNodeListsです。

例:

let arr = ['el1', 'el2', 'el3'];

arr.addedProp = 'arrProp';

// elKey are the property keys
for (let elKey in arr) {
  console.log(elKey);
}

// elValue are the property values
for (let elValue of arr) {
  console.log(elValue)
}

この例では、for..inループがオブジェクトのキー(この例では配列オブジェクト)を反復処理することがわかります。キーは0、1、2で、追加した配列要素とaddedPropに対応しています。これがarr配列オブジェクトがchrome devtools内でどのように見えるかです:

enter image description here

あなたは私たちのfor..inループが単にこれらの値を反復すること以上の何もしないのを見ます。


この例のfor..ofループは、データ構造の values を反復処理します。この特定の例の値は'el1', 'el2', 'el3'です。 for..ofを使用して反復可能なデータ構造体が返す値は、反復可能なオブジェクトの種類によって異なります。たとえば、配列はすべての配列要素の値を返しますが、文字列は文字列のすべての個々の文字を返します。

6

Array、Map、String Objectsなど、定義済みのデータ型がいくつかあり、それらを簡単に繰り返し処理することができます。

Normal for inはイテレータを反復処理し、それに応答して、以下の例に示すように挿入順のキーを提供します。

  const numbers = [1,2,3,4,5];
   for(let number in number) {
     console.log(number);
   }

   // result: 0, 1, 2, 3, 4

これで、forを使って同じことを試みると、それに応じて、キーではなく値が返されます。例えば

  const numbers = [1,2,3,4,5];
   for(let numbers of numbers) {
    console.log(number);
  }

  // result: 1, 2, 3, 4, 5

そのため、両方のイテレータを見れば、両者の違いを簡単に区別できます。

注: - forはSymbol.iteratorでのみ機能します。

それで、もし私たちが通常のオブジェクトを反復しようとすると、それは私たちにエラーを与えるでしょう。

const Room = {
   area: 1000,
   height: 7,
   floor: 2
 }

for(let prop in Room) {
 console.log(prop);
 } 

// Result area, height, floor

for(let prop of Room) {
  console.log(prop);
 } 

部屋はイタラブルではない

今度は反復するためにES6 Symbol.iteratorを定義する必要があります。

  const Room= {
    area: 1000, height: 7, floor: 2,
   [Symbol.iterator]: function* (){
    yield this.area;
    yield this.height;
    yield this.floors;
  }
}


for(let prop of Room) {
  console.log(prop);
 } 

//Result 1000, 7, 2

これがFor inFor ofの違いです。それが違いを明確にするかもしれないことを願っています。

5
Amit Mundra

for...inステートメントは、オブジェクトの列挙可能なプロパティを任意の順序で繰り返します。列挙可能なプロパティは、内部[[Enumerable]]フラグがtrueに設定されているプロパティです。したがって、プロトタイプチェーンに列挙可能なプロパティがある場合は、for...inループもそれらを繰り返します。

for...ofステートメントは、反復可能オブジェクトが反復対象として定義しているデータを反復します。

例:

Object.prototype.objCustom = function() {}; 
Array.prototype.arrCustom = function() {};

let iterable = [3, 5, 7];

for (let i in iterable) {
  console.log(i); // logs: 0, 1, 2, "arrCustom", "objCustom"
}

for (let i in iterable) {
  if (iterable.hasOwnProperty(i)) {
    console.log(i); // logs: 0, 1, 2,
  }
}

for (let i of iterable) {
  console.log(i); // logs: 3, 5, 7
}

以前のように、for...ofループにhasOwnPropertyを追加することをスキップすることができます。

5
Ramandeep Sohi

誰もがこの問題が発生する理由を説明しましたが、それを忘れること、そして間違った結果を得た理由を頭に掻くことは依然として非常に簡単です。一見したところ結果が問題ないと思われるときに、特に大量のデータを処理しているときは特にそうです。

Object.entriesを使用すると、すべてのプロパティを確実に通過できます。

var arr = [3, 5, 7];
arr.foo = "hello";

for ( var [key, val] of Object.entries( arr ) ) {
   console.log( val );
}

/* Result:

3
5
7
hello

*/
1
David C.

2つのループの間のもう1つの違い 。これまで誰も言及していません( source )。

for...inの非構造化は推奨されていません。代わりにfor...ofを使用してください。

したがって、ループ内で destructuring を使用したい場合は、各array要素のindexvalueの両方を取得します。 for...ofループをArrayメソッド entries() と一緒に使用する必要があります。

for (const [idx, el] of arr.entries()) {
    console.log( idx + ': ' + el );
}
0
simhumileco

良い答えはたくさんありますが、良い例を示すために5セントを入れることにしました。

ループ内

列挙可能なすべての小道具を反復処理する

let nodes = document.documentElement.childNodes;

for (var key in nodes) {
  console.log( key );
}

Forループ

反復可能な値すべてについて反復します

let nodes = document.documentElement.childNodes;

for (var node of nodes) {
  console.log( node.toString() );
}
0
WebBrother

https://javascript.info/array から次の説明を見つけました。

配列項目を循環させる最も古い方法の1つは、インデックスに対するforループです。

let arr = ["Apple", "Orange", "Pear"];

for (let i = 0; i < arr.length; i++) { alert( arr[i] ); } But for arrays there is another form of loop, for..of:

let fruits = ["Apple", "Orange", "Plum"];

// iterates over array elements for (let fruit of fruits) { alert( fruit ); } The for..of doesn’t give access to the number of the current element, just its value, but in most cases that’s enough. And it’s shorter.

技術的には、配列はオブジェクトであるため、for..inを使用することもできます。

let arr = ["Apple", "Orange", "Pear"];

for (let key in arr) { alert( arr[key] ); // Apple, Orange, Pear } But that’s actually a bad idea. There are potential problems with it:

For..inのループは、数値のプロパティだけでなく、すべてのプロパティを繰り返し処理します。

ブラウザやその他の環境には、配列のように見えるいわゆる「配列のような」オブジェクトがあります。つまり、長さとインデックスのプロパティがありますが、通常は必要ない他の非数値のプロパティとメソッドもあります。 for..inループはそれらをリストします。したがって、配列のようなオブジェクトを操作する必要がある場合、これらの「余分な」プロパティが問題になる可能性があります。

For..inループは、配列ではなく汎用オブジェクト用に最適化されているため、10〜100倍遅くなります。もちろん、まだ非常に高速です。高速化はボトルネックでのみ問題になる場合があります。しかし、まだ違いに注意する必要があります。

通常、for..inを配列に使用するべきではありません。

0
Albert Leung