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)
}
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)
}
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];
}
.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 wsparcie nie działa w IE lub iOS Safari. Będzieszprawdopodobnie może wymagać wypełnienia.
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 dlaObject.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
i Object.keys
:
var obj = { a: 'foo', z: 'bar', m: 'baz' };
Object.keys(obj).forEach(function (prop) {
var value = obj[prop];
console.log(value);
});
Object.entries
można wypełnić polietylenem bez dotykania prototypu.
for-in
?
Iterator, Iterable i for..of w ECMAScript 2015 / ES6
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!!!!!!
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({})) { }
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.
for(let key in obj){
console.log(obj[key]);
}
Object.keys(obj).forEach(function(key){
console.log(obj[key]);
});
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.
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ć tej Object.keys()
metody. Ta metoda zwraca Array
obiekt, który ma już wbudowany iterator, więc możesz go użyć z for...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
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ó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]);
}
Albo w ten sposób
var it = t[Symbol.iterator](), p;
while(p = it.next().value){
console.log(t[p])
}
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]}`))
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);
}
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.