Почему нельзя использовать объекты в циклах for? Или это глюк браузера? Этот код не работает в Chrome 42, говоря, что undefined не является функцией:
test = { first: "one"}
for(var item of test) {
console.log(item)
}
Почему нельзя использовать объекты в циклах for? Или это глюк браузера? Этот код не работает в Chrome 42, говоря, что undefined не является функцией:
test = { first: "one"}
for(var item of test) {
console.log(item)
}
цикл for..of поддерживает только итерируемые объекты как массивы, а не объекты.
Чтобы перебрать значения объекта, используйте:
for (var key in test) {
var item = test[key];
}
Object.values
.
- person Oriol; 27.04.2015
.iterable
, откуда возникает ошибка, когда вы пытаетесь использовать ее для объекта (у которого ее нет). developer.mozilla.org/en-US/docs/Web/ JavaScript/Справочник/
- person Overv; 27.04.2015
if (test.hasOwnProperty(key)){ ... }
? Или это не нужно?
- person tennisgent; 14.09.2016
{}
или получаете его из json с помощью JSON.Parse
, hasOwnProperty
глобально бесполезен. Но…: stackoverflow.com/a/11314053/1250044
- person yckart; 07.05.2017
Вы можете использовать этот синтаксис:
const myObject = {
first: "one",
second: "two",
};
for (const [key, value] of Object.entries(myObject)) {
console.log(key, value); // first one, second two
}
Однако Object.entries
имеет плохую поддержку сейчас не работает в IE или iOS Safari. Вам возможно может понадобиться полифилл. См. https://caniuse.com/mdn-javascript_builtins_object_entries для получения последней информации.
См. также Object.keys
для повторения только ключей или Object.values
только для значений.
Если вы храните данные в хранилище "ключ-значение", < strong>пожалуйста, используйте 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()
И, наконец, если вы поддерживаете более старую среду, которая не поддерживает этот синтаксис, вам придется прибегнуть к использованию forEach
и 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
можно полифилить, не касаясь прототипа.
- person mpen; 11.08.2016
for-in
?
- person 1252748; 17.08.2017
Iterator, Iterable и цикл for..of в ECMAScript 2015/ES6
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, который придерживается < strong>Протокол итератора, что означает, что он должен иметь объект с методом next. Следующий метод не принимает аргументов и должен возвращать объект с этими двумя свойствами.
done: сигнализирует, что последовательность завершена, когда true, а false означает, что могут быть другие значения value: это текущий элемент в последовательности
Итак, чтобы сделать объект Итерируемым, чтобы он работал с for..of, мы можем:
1. Сделайте объект Итерируемым, назначив его мистическое свойство @@iterator через свойство Symbol.iterator. Вот как это сделать:
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. Используйте Object.entries, который возвращает 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. Используйте Object.keys следующим образом:
let tempObj = {a:1, b:2, c:3};
for (let key of Object.keys(tempObj)) {
console.log(key);
}
// a
// b
// c
Надеюсь это поможет!!!!!!
Я сделал объекты итерируемыми с помощью этого кода:
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({})) { }
Object.keys
. Одна из приятных особенностей генераторов заключается в том, что их можно лениво соединять в цепочку. Вызов Object.keys
разрушает лень, жадно создавая новый массив ключей. Лучшим решением было бы использовать for in
с hasOwnProperty
чеком или propertyIsEnumerable
чеком, затем уступает
- person Rico Kahler; 25.05.2017
for in
тоже жадно хватает ключи, то нет никакой разницы. это мелочь, разница в производительности, вероятно, незначительна.
- person Rico Kahler; 25.05.2017
for in
быстрее. Вы можете подтвердить в своем браузере?
- person Rico Kahler; 25.05.2017
Object.prototype[Symbol.iterator]
может сломать любой другой соответствующий спецификации фрагмент кода. Если вам нужно настроить встроенное поведение класса, создайте его подкласс, это всегда так просто. Например. то же самое, но сделано правильно.
- person Estus Flask; 01.09.2017
Поскольку литерал объекта не имеет свойства Symbol.iterator . Чтобы быть точным, вы можете перебирать только String, Массив, Карта, Set, аргументы, NodeList (не широко поддерживается) и Генератор с for...of.
Чтобы иметь дело с итерацией Object Literal, у вас есть два варианта.
for(let key in obj){
console.log(obj[key]);
}
Object.keys(obj).forEach(function(key){
console.log(obj[key]);
});
Ответ: Нет. Невозможно использовать For..Of с литералами Object.
Я согласен с Overv, что For..Of предназначен только для итераций. У меня был точно такой же вопрос, потому что я использую объекты для перебора ключей и значений с помощью for..in. Но я только что понял, что это то, что ES6 MAPS и SETS для.
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().
Кроме того, ваши ключи не ограничены строками. Вы можете использовать числа, объекты или другие литералы.
Литералы объектов не имеют встроенных итераторов, которые необходимы для работы с циклами 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
Можно определить итератор для любого объекта, таким образом, вы можете поместить различную логику для каждого объекта.
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])
}
Я просто сделал следующее, чтобы легко утешить свои вещи.
for (let key in obj) {
if(obj.hasOwnProperty(key){
console.log(`${key}: ${obj[key]}`);
}
}
Как насчет использования Object.keys получить массив ключей? А затем для каждого в массиве?
obj = { a: 1, b:2}
Object.keys(obj).forEach( key => console.log(`${key} => ${obj[key]}`))
Как насчет использования
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);
}
в 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"
– текущее состояние итерации в логическом значении.
Используя уничтожение массива, вы можете повторить его следующим образом, используя 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"
});