Dlaczego nie można używać obiektów w pętlach for of? A może to błąd przeglądarki? 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)
}
javascript
for-loop
ecmascript-6
iterable
Daniel Herr
źródło
źródło
Odpowiedzi:
For..of pętla obsługuje tylko iterowalny obiektów, takich jak macierze, nie sprzeciwia.
Aby iterować po wartościach obiektu, użyj:
for (var key in test) { var item = test[key]; }
źródło
.iterable
funkcji członkowskiej, która jest przyczyną błędu, gdy próbujesz użyć jej na obiekcie (który jej nie ma). developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…if (test.hasOwnProperty(key)){ ... }
? Czy to nie jest potrzebne?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,
Object.entries
ma teraz słabe wsparcienie działa w IElub iOS Safari. Będzieszprawdopodobniemoże wymagać wypełnienia.źródło
Jeśli przechowujesz dane w magazynie klucza i wartości, użyj go,
Map
który jest wyraźnie przeznaczony 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 nie jest to jeszcze obsługiwane, użyj wypełnienia: alternatywna wersja dla
Object.values()
I na koniec, jeśli obsługujesz starsze środowisko, które nie obsługuje tej składni, będziesz musiał uciec się do używania
forEach
iObject.keys
:var obj = { a: 'foo', z: 'bar', m: 'baz' }; Object.keys(obj).forEach(function (prop) { var value = obj[prop]; console.log(value); });
źródło
Object.entries
można wypełnić polietylenem bez dotykania prototypu.for-in
?let tempArray = [1,2,3,4,5]; for(element of tempArray) { console.log(element); } // 1 // 2 // 3 // 4 // 5
Ale jeśli to zrobimy
let tempObj = {a:1, b:2, c:3}; for(element of tempObj) { console.log(element); } // error
Otrzymujemy błąd, ponieważ pętla for..of działa tylko na Iterables , czyli na obiekcie, który ma iterator @@, który jest zgodny z protokołem Iterator , co oznacza, że musi mieć obiekt z następną metodą. Następna metoda nie przyjmuje argumentów i powinna zwrócić obiekt z tymi dwiema właściwościami.
gotowe : sygnalizuje zakończenie sekwencji, gdy prawda, a fałsz oznacza, że może być więcej wartości wartość : to jest bieżąca pozycja w sekwencji
Tak więc, aby obiekt był iterowalny , to znaczy, że będzie działał z … z , możemy:
1 .Dokonać obiekt iterowalny poprzez przypisanie To mistyczne @@ iterator nieruchomość przez Symbol.iterator property.Here sposób:
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.Wykorzystanie Object.entries , który zwraca 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. Użyj Object.keys , 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!!!!!!
źródło
Zrobiłem iterowalne obiekty za pomocą tego kodu:
Object.prototype[Symbol.iterator] = function*() { for(let key of Object.keys(this)) { yield([ key, this[key] ]) } }
Stosowanie:
for(let [ key, value ] of {}) { }
Alternatywnie:
for(let [ key, value ] of Object.entries({})) { }
źródło
Ponieważ literał obiektu nie ma właściwości Symbol.iterator . Mówiąc konkretnie, możesz iterować tylko po Stringach , Array , Map , Set , arguments , NodeList (nie jest szeroko obsługiwany) i Generatorze z pętlą for ... of .
Aby poradzić sobie z iteracją dosłowną obiektu, masz dwie opcje.
dla w
for(let key in obj){ console.log(obj[key]); }
Object.keys + forEach
Object.keys(obj).forEach(function(key){ console.log(obj[key]); });
źródło
Odpowiedź brzmi: Nie. Nie można używać For..Of z literałami Object.
Zgadzam się z Overv, że For..Of jest tylko dla iterable. Miałem dokładnie to samo pytanie, ponieważ używam Objects do iteracji po kluczach i wartościach z for..in. Ale właśnie zdałem sobie sprawę, że do tego służą MAPY i ZESTAWY ES6 .
let test = new Map(); test.set('first', "one"); test.set('second', "two"); for(var item of test) { console.log(item); // "one" "two" }
W związku z tym, że osiąga się cel nie trzeba wykorzystywać for..in (stwierdzenia prawidłowości z hasOwnProperty ) i bez konieczności korzystania Object.keys ().
Ponadto twoje klucze nie są ograniczone do ciągów. Możesz używać liczb, obiektów lub innych literałów.
źródło
Literały obiektów nie mają wbudowanych iteratorów, które są wymagane do pracy z
for...of
pętlami. Jeśli jednak nie chcesz kłopotać się dodawaniem własnego[Symbol.iterator]
obiektu do obiektu, możesz po prostu użyć tejObject.keys()
metody. Ta metoda zwracaArray
obiekt, który ma już wbudowany iterator, więc możesz go użyć zfor...of
pętlą taką jak ta: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
źródło
Możliwe jest zdefiniowanie iteratora dla dowolnego obiektu podającego, 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 wykonaj iterację bezpośrednio
x
for (let i in x){ console.log(i); } //1 //foo //last
Można zrobić to samo na
Object.prototype
obiekcie i mieć ogólny iterator dla wszystkich obiektówObject.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]); }
Albo w ten sposób
var it = t[Symbol.iterator](), p; while(p = it.next().value){ console.log(t[p]) }
źródło
Wykonałem tylko następujące czynności, aby łatwo pocieszyć moje rzeczy.
for (let key in obj) { if(obj.hasOwnProperty(key){ console.log(`${key}: ${obj[key]}`); } }
źródło
A co powiesz na użycie Object.keys do uzyskania tablicy kluczy? A potem forEach w Array ?
obj = { a: 1, b:2} Object.keys(obj).forEach( key => console.log(`${key} => ${obj[key]}`))
źródło
A co z używaniem
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); }
źródło
w ES6 możesz iść 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 plik jsfiddle. W wyniku otrzymasz obiekt z klawiszami
"value"
i"done"
."Value"
zawiera wszystko, co chcesz , aby miał i"done"
jest bieżącym stanem iteracji w bool.źródło
Używając niszczenia tablicy, możesz iterować w następujący sposób, używając
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" });
źródło