Używanie obiektów w pętlach For of

Dlaczego nie można używać obiektów w pętlach For of? A może to błąd w przeglądarce? Ten kod nie działa w Chrome 42, mówiąc, że undefined nie jest funkcją:

test = { first: "one"}

for(var item of test) {
  console.log(item)
}
Author: Daniel Herr, 2015-04-27

13 answers

Dla..of loop obsługuje tylko obiekty iteracyjne, takie jak tablice, a nie Obiekty.

Aby iterować nad wartościami obiektu, użyj:

for (var key in test) {
    var item = test[key];
}
 54
Author: Overv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-27 00:31:05

Jeśli przechowujesz dane w magazynie klucz-wartość, Proszę użyć Map który jest specjalnie zaprojektowany do tego celu.

Jeśli jednak musisz użyć obiektu, ES2017 (ES8) pozwala na użycie Object.values:

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

Jeśli to nie jest jeszcze obsługiwane, użyj polyfill: alternatywna wersja dla Object.values()

I wreszcie, jeśli wspierasz starsze środowisko, które nie obsługuje tej składni, będziesz musiał uciekać się do używania forEach i Object.keys:

var obj = { a: 'foo', z: 'bar', m: 'baz' };
Object.keys(obj).forEach(function (prop) {
    var value = obj[prop];
    console.log(value);
});
 29
Author: Qantas 94 Heavy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-15 03:26:30

Możesz użyć tej składni:

let myObject = {first: "one"};

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

Jednakże, Object.entries ma słabe wsparcie w tej chwili nie działa w IE lub iOS Safari. Pewnie będziesz potrzebował wypełniacza.

 24
Author: mpen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-15 23:16:43

Zrobiłem obiekty iterowalne za pomocą tego kodu:

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

Użycie:

for(let [ key, value ] of {}) { }
 18
Author: Daniel Herr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-13 00:23:02

Iterator, Iterable I for..z pętli w 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

Otrzymujemy błąd ponieważ dla..ofloop działa tylko na Iterables, czyli obiekcie, który ma @@iterator, który przylega do protokołu iteracyjnego, co oznacza, że musi mieć obiekt z next} metoda. Następna metoda nie pobiera argumentów i powinna zwrócić obiekt z tymi dwoma właściwości.

Done: sygnalizuje, że sekwencja zakończyła się, gdy true, a false oznacza, że może być więcej wartości wartość : jest to bieżąca pozycja w sekwencji

Tak więc, aby obiekt był iteracyjny , czyli aby działał z dla..z możemy:

1 .Uczyń obiekt Iterable {[13] } przypisując do niego mistyczną @ @ iterator właściwość za pomocą symbolu .iterator właściwość.Oto jak:

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.Użyj Obiektu.wpisy , które zwracają Iterowalne:

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.Użyj Obiektu.klucze , Oto jak:

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

// a
// b
// c
Mam nadzieję, że to pomoże!!!!!!
 17
Author: Manishz90,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-25 17:57:49

Ponieważ obiekt nie posiada symbolu .iterator właściwość. Aby być dokładnym, możesz tylko iterację nad String, Array, mapka, Set, argumenty, NodeList (nie jest szeroko wspierany) i Generator z dla...of loop.

Aby poradzić sobie z iteracją obiektową, masz dwie opcje.

For...in

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

Obiekt.klucze + forEach

Object.keys(obj).forEach(function(key){
    console.log(obj[key]);
});
 12
Author: Lewis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-29 04:23:17

Odpowiedź brzmi nie. Nie da się tego użyć..Z literałami obiektowymi.

Zgadzam się z tym za..Of Jest Tylko dla iterables. Miałem dokładnie to samo pytanie, ponieważ używam obiektów do iteracji kluczy i wartości z for..in ale właśnie zdałem sobie sprawę, że do tego służą mapy ES6 i zestawy .
let test = new Map();
test.set('first', "one");
test.set('second', "two");

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

Stąd osiąga cel nie konieczności używania for..In (Walidacja za pomocą hasOwnProperty) i brak konieczności używania obiektu.klucze ().

Dodatkowo, Twoje klucze nie są ograniczone do ciągów. Możesz używać liczb, obiektów lub innych liter.

 2
Author: cuadraman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-27 04:21:55

Literały obiektów nie mają wbudowanych iteratorów, które są wymagane do pracy z pętlami for...of. Jeśli jednak nie chcesz zadawać sobie trudu dodawania własnego [Symbol.iterator] do obiektu, możesz po prostu użyć metody Object.keys(). Ta metoda zwraca obiekt Array, który ma już wbudowany iterator, więc można go używać z pętlą for...of w następujący sposób:

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
 2
Author: TheDarkIn1978,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-26 02:41:53

Możliwe jest zdefiniowanie iteratora nad dowolnym obiektem, w ten sposób można umieścić inną logikę dla każdego obiektu

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

Następnie po prostu bezpośrednio iteratuj x

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

Można zrobić to samo na obiekcie Object.prototype i mieć ogólny iterator dla wszystkich obiektów

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

Następnie iteruj swój obiekt w ten sposób

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

Lub w ten sposób

var it = t[Symbol.iterator](), p;
while(p = it.next().value){
    console.log(t[p])
}
 1
Author: Yaki Klein,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-29 11:19:03

Zrobiłem następujące rzeczy, aby łatwo pocieszyć moje rzeczy.

for (let key in obj) {
  if(obj.hasOwnProperty(key){
    console.log(`${key}: ${obj[key]}`);
  }
}
 1
Author: DaFrenzy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-25 17:54:39

A co z użyciem

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
Author: user1703761,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-11 21:44:49

W ES6 można przejść z generatorem:

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}

Oto jsfiddle. W wyniku otrzymamy obiekt z klawiszami "value" i "done". "Value" zawiera wszystko, co chcesz , aby miało i "done" jest aktualnym stanem iteracji w bool.

 0
Author: Serge Nikolaev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-01 12:18:39

Może użyjesz obiektu.klucze aby uzyskać tablicę kluczy? A potem forEach na tablicy ?

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

 0
Author: justingordon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-22 02:33:56