Using Objects in For Of Loops

时光毁灭记忆、已成空白 提交于 2019-12-27 17:06:34

问题


Why isn't is possible to use objects in for of loops? Or is this a browser bug? This code doesn't work in Chrome 42, saying undefined is not a function:

test = { first: "one"}

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

回答1:


The for..of loop only supports iterable objects like arrays, not objects.

To iterate over the values of an object, use:

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



回答2:


You can use this syntax:

let myObject = {first: "one"};

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

However, Object.entries has poor support right now does not work in IE or iOS Safari. You'll probably might need a polyfill.




回答3:


If you are storing data in a key-value store, please use Map which is explicitly designed for this purpose.

If you have to use an object though, ES2017 (ES8) allows you to use Object.values:

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

If that isn't supported yet, use a polyfill: Alternative version for Object.values()

And finally if you're supporting an older environment that don't support this syntax, you'll have to resort to using forEach and Object.keys:

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



回答4:


Iterator, Iterable and for..of loop in ECMAScript 2015/ ES6

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

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

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

But if we do

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

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

We get error because for..of loop works only on Iterables, that is, the object which has an @@iterator that adheres to Iterator protocol, meaning it must have an object with a next method. The next method takes no arguments and it should return an object with these two properties.

done: signals that the sequence has ended when true, and false means there may be more values value: this is the current item in the sequence

So, to make an object Iterable that is to make it work with for..of we can:

1 .Make an object an Iterable by assigning to it’s mystical @@iterator property through the Symbol.iterator property.Here is how:

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, which returns an Iterable:

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.Use Object.keys, here is how:

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

// a
// b
// c

Hope this helps!!!!!!




回答5:


I made objects iterable with this code:

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

Usage:

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

Alternativly:

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



回答6:


Because object literal does not have the Symbol.iterator property. To be specific, you can only iterate over String, Array, Map, Set, arguments, NodeList(not widely support) and Generator with for...of loop.

To deal with Object Literal iteration, you have two options.

for...in

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

Object.keys + forEach

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



回答7:


The answer is No. It's not possible to use For..Of with Object literals.

I agree with Overv that For..Of is only for iterables. I had exactly the same question because I use Objects to iterate over keys and values with for..in. But I just realized that that's what ES6 MAPS and SETS are for.

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

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

Hence it achieves the goal of not having to use for..In (validating with hasOwnProperty) and not having to use Object.keys().

Additionally, your keys aren't limited to strings. You can use numbers, objects, or other literals.




回答8:


Object literals don't have built-in iterators, which are required to work with for...of loops. However, if you don't want to go thru the trouble of adding your own [Symbol.iterator] to your object, you can simply use the Object.keys() method. This method returns an Array object, which already has a built-in iterator, so you can use it with a for...of loop like this:

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



回答9:


It is possible to define an iterator over any giving object, this way you can put different logic for each object

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

Then just directly iterate x

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

It is possible to do the same thing on the Object.prototype object And have a general iterator for all objects

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

then iterate your object like this

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

Or this way

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



回答10:


I just did the following to easily console out my stuff.

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



回答11:


What about using

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);
}



回答12:


in ES6 you could go with generator:

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}

Here is the jsfiddle. In the output you will get an object with the "value" and "done" keys. "Value" contains everything you want it to have and "done" is current state of the iteration in bool.




回答13:


Using Array Destruction you can iterate it as follows using 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"
});



回答14:


How about using Object.keys to get an array of keys? And then forEach on the Array?

obj = { a: 1, b:2}
Object.keys(obj).forEach( key => console.log(`${key} => ${obj[key]}`))


来源:https://stackoverflow.com/questions/29885220/using-objects-in-for-of-loops

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!