ForOfループでのオブジェクトの使用


83

forループでオブジェクトを使用できないのはなぜですか?それともこれはブラウザのバグですか?このコードはChrome42では機能せず、undefinedは関数ではないと言っています。

test = { first: "one"}

for(var item of test) {
  console.log(item)
}

テストは配列またはオブジェクトですか?
キックザびっくり2015

9
@KickButtowski、見えませんか?それは間違いなくオブジェクトです。

4
for(let key of Object.keys(test)){...}
clocksmith 2017

回答:


69

ループfor..ofだけでなく、オブジェクト、配列などの反復可能なオブジェクトをサポートしています。

オブジェクトの値を反復処理するには、次を使用します。

for (var key in test) {
    var item = test[key];
}

3
@DanielHerr.iterableメンバー関数があります。これは、オブジェクト(オブジェクトがない)で使用しようとしたときにエラーが発生する場所です。developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
Overv

4
つまり、なぜオブジェクトにそれがないのですか?ネイティブに追加する場合の問題は何ですか?
Daniel Herr 2015

3
@DanielHerr私にはその答えがありません、あなたは言語を設計する人々に尋ねなければならないでしょう。
overv 2015

6
@DanielHerrオブジェクトの「基本クラス」が反復可能である場合、他の複雑さの中でも特に関数/日付などの「サブクラス」も反復可能です。ただし、質問のより徹底的で正確な説明については、esdiscuss.org / topic / es6-iteration-over-object-values#content-5を参照してください。
natevw 2016

5
このfor..inソリューションでは、技術的にチェックする必要はありif (test.hasOwnProperty(key)){ ... }ませんか?それともそれは必要ありませんか?
Tennisgent 2016

39

次の構文を使用できます。

let myObject = {first: "one"};

for(let [key, value] of Object.entries(myObject)) {
    console.log(key, value); // "first", "one"
}

しかしながら、 Object.entries 現在サポートが不十分です IEでは機能しません またはiOSSafari。あなたは多分 ポリフィルが必要な場合があります。


33

Key-Valueストアにデータを保存する場合は、この目的のために明示的に設計されたものを使用しMapください

ただし、オブジェクトを使用する必要がある場合は、ES2017(ES8)で次のものを使用できますObject.values

const foo = { a: 'foo', z: 'bar', m: 'baz' };
for (let value of Object.values(foo)) {
    console.log(value);
}

それはまだサポートされていない場合は、ポリフィルを使用:するための別のバージョンをObject.values()

そして最後に、この構文をサポートしていない古い環境をサポートしている場合は、forEachandを使用する必要がありますObject.keys

var obj = { a: 'foo', z: 'bar', m: 'baz' };
Object.keys(obj).forEach(function (prop) {
    var value = obj[prop];
    console.log(value);
});

これをサポートするためにオブジェクトプロトタイプを拡張できませんでしたか?
ソニックソウル

1
@SonicSoul:技術的にはそうですが、(ほとんど)すべてがそれから継承するため、オブジェクトプロトタイプを拡張することは一般的にはお勧めできません。
カンタス94ヘビー

1
Object.entriesプロトタイプに触れることなくポリフィルすることができます。
mpen 2016

5
オブジェクトの代わりにマップを使用するのはなぜですか?
Daniel Herr 2016年

1
これらの複雑な例を単純な例よりも使用することに利点はありますfor-inか?
1252748 2017

18

ECMAScript 2015 / ES6のIterator、Iterable、およびfor..ofループ

let tempArray = [1,2,3,4,5];

for(element of tempArray) {
  console.log(element);
}

// 1
// 2
// 3
// 4
// 5

しかし、私たちがそうするなら

let tempObj = {a:1, b:2, c:3};

for(element of tempObj) {
   console.log(element);
}
// error

for..ofループはIterables、つまりIteratorプロトコルに準拠する@@ iteratorを持つオブジェクトでのみ機能するため、エラーが発生します。つまり、次のメソッドを持つオブジェクトが必要です。次のメソッドは引数をとらず、これら2つのプロパティを持つオブジェクトを返す必要があります。

完了:trueの場合にシーケンスが終了したことを示し、falseはより多くの値がある可能性があることを意味します value:これはシーケンスの現在の項目です

したがって、オブジェクトをIterableにすること、つまり、オブジェクトをfor..ofで動作させることは、次のことができます。

1 .MakeオブジェクトのIterable神秘のITに割り当てることによって@@イテレータ を介してプロパティSymbol.iterator property.Hereの方法です:

let tempObj = {a:1, b:2, c:3};

tempObj[Symbol.iterator]= () => ({
next: function next () {
return {
    done: Object.keys(this).length === 0,
    value: Object.keys(this).shift()
     }
    }
  })

for(key in tempObj){
 console.log(key)
}
// a
// b
// c

2.Use Object.entries戻り、反復処理可能に

let tempObj = {a:1, b:2, c:3};

for(let [key, value] of Object.entries(tempObj)) {
    console.log(key, value);
}
// a 1
// b 2
// c 3

3.Object.keysを使用しますます。方法は次のとおりです。

let tempObj = {a:1, b:2, c:3};
for (let key of Object.keys(tempObj)) {
    console.log(key);
}

// a
// b
// c

お役に立てれば!!!!!!


16

このコードでオブジェクトを反復可能にしました:

Object.prototype[Symbol.iterator] = function*() {
 for(let key of Object.keys(this)) {
  yield([ key, this[key] ])
} }

使用法:

for(let [ key, value ] of {}) { }

代わりに:

for(let [ key, value ] of Object.entries({})) { }

47
なぜこれが受け入れられた解決策であるのか分かりません。ポリフィルが常にひどい考えでない限り、プロトタイプを変更する。
user1703761 2016

2
@ user1703761動作するため、受け入れられているソリューションです。それがひどい場合、これがどのような問題を引き起こすかを説明してください。
Daniel Herr 2016

9
あらゆる種類の問題があり、主に上位互換性の問題があります。一例としては、たArray.prototype.includesが以前の名前が含まれているが、武ツールのプロトタイプを拡張し、実装を見、互換性がありませんでしたということですbugzilla.mozilla.org/show_bug.cgi?id=1075059 またプロトタイプライブラリdesasterを調べます;)
user1703761 2016

4
イテレータがオブジェクトに追加された場合は上書きされ、イテレータがオブジェクトサブタイプに追加された場合はサブタイプイテレータが使用されるため、これには上位互換性の問題はないと思います。
Daniel Herr 2016

4
やあみんな、プロトタイプを変更するのは悪い考えです!!! 実際に質問に答えてくれたOPを恥じましょう!
NiCk Newman 2016

12

オブジェクトリテラルにはSymbol.iteratorプロパティがないためです。具体的には、StringArrayMapSetargumentsNodeList(広くサポートされていない)、および for ... ofループを使用したGeneratorに対してのみ反復できます。

オブジェクトリテラルの反復を処理するには、2つのオプションがあります。

for ... in

for(let key in obj){
    console.log(obj[key]); 
}

Object.keys + forEach

Object.keys(obj).forEach(function(key){
    console.log(obj[key]);
});

3

答えは「いいえ」です。オブジェクトリテラルでFor..Ofを使用することはできません。

For..Ofは反復可能のみであるというOvervに同意します。オブジェクトを使用してfor..inでキーと値を反復処理するため、まったく同じ質問がありました。しかし、私はちょうどそれがES6ものだと認識MAPSセットがためのものです。

let test = new Map();
test.set('first', "one");
test.set('second', "two");

for(var item of test) {
  console.log(item); // "one" "two"
}

したがって、for..In(hasOwnPropertyで検証)を使用する必要がなく、Object.keys()を使用する必要がないという目標を達成します。

さらに、キーは文字列に限定されません。数字、オブジェクト、またはその他のリテラルを使用できます。


2

オブジェクトリテラルには、for...ofループを操作するために必要な組み込みのイテレータがありません。ただし、[Symbol.iterator]オブジェクトに独自のオブジェクトを追加する手間をかけたくない場合は、このObject.keys()メソッドを使用するだけで済みます。このメソッドは、Arrayすでにイテレータが組み込まれているオブジェクトを返すため、次のfor...ofようなループで使用できます。

const myObject = {
    country: "Canada",
    province: "Quebec",
    city: "Montreal"
}

for (let i of Object.keys(myObject)) {
    console.log("Key:", i, "| Value:", myObject[i]);
}

//Key: country | Value: Canada
//Key: province | Value: Quebec
//Key: city | Value: Montreal

毎回キーを使用することは、イテレータを1回追加するよりも面倒です。また、Object.keys()はES5です。
Daniel Herr 2016

1

任意のオブジェクトに対してイテレータを定義することが可能です。このようにして、オブジェクトごとに異なるロジックを配置できます。

var x = { a: 1, b: 2, c: 3 }
x[Symbol.iterator] = function* (){
    yield 1;
    yield 'foo';
    yield 'last'
}

次に、直接繰り返します x

for (let i in x){
    console.log(i);
}
//1
//foo
//last

Object.prototypeオブジェクトに対して同じことを行うことが可能であり、すべてのオブジェクトに対して一般的なイテレータがあります

Object.prototype[Symbol.iterator] = function*() {
    for(let key of Object.keys(this)) {
         yield key 
    } 
 }

次に、このようにオブジェクトを繰り返します

var t = {a :'foo', b : 'bar'}
for(let i of t){
    console.log(t[i]);
}

またはこのように

var it = t[Symbol.iterator](), p;
while(p = it.next().value){
    console.log(t[p])
}

1

私は自分のものを簡単に慰めるために次のことをしました。

for (let key in obj) {
  if(obj.hasOwnProperty(key){
    console.log(`${key}: ${obj[key]}`);
  }
}


0

使用するのはどうですか

function* entries(obj) {
    for (let key of Object.keys(obj)) {
        yield [key, obj[key]];
    }
}

for ([key, value] of entries({a: "1", b: "2"})) {
    console.log(key + " " + value);
}

0

ES6では、ジェネレーターを使用できます。

var obj = {1: 'a', 2: 'b'};

function* entries(obj) {
  for (let key of Object.keys(obj)) {
    yield [key, obj[key]];
  }
}

let generator = entries(obj);

let step1 = generator.next();
let step2 = generator.next();
let step3 = generator.next();

console.log(JSON.stringify(step1)); // {"value":["1","a"],"done":false}
console.log(JSON.stringify(step2)); // {"value":["2","b"],"done":false}
console.log(JSON.stringify(step3)); // {"done":true}

これがjsfiddleです。 出力では"value""done"キーとキーを持つオブジェクトを取得します。"Value"あなたがすべて含まれていたい、それが持っているのと"done"BOOLにおける反復の現在の状態です。


0

Array Destructionを使用すると、次のように繰り返すことができます。 forEach

const obj = { a: 5, b: 7, c: 9 };

Object.entries(obj).forEach(([key, value]) => {
  console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
});
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.