Чому не можна використовувати об'єкти у циклах for for? Або це помилка браузера? Цей код не працює в Chrome 42, кажучи, що undefined не є функцією:
test = { first: "one"}
for(var item of test) {
console.log(item)
}
Чому не можна використовувати об'єкти у циклах for 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];
}
.iterable
функції-члена, звідки і виникає помилка при спробі використовувати її на об’єкті (який її не має). developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
if (test.hasOwnProperty(key)){ ... }
? Або це не потрібно?
Ви можете використовувати цей синтаксис:
let myObject = {first: "one"};
for(let [key, value] of Object.entries(myObject)) {
console.log(key, value); // "first", "one"
}
Однак Object.entries
зараз має погану підтримку не працює в IE або iOS Safari. Ви будетеймовірно можливо знадобиться полізаповнювач.
Якщо ви зберігаєте дані у сховищі ключ-значення, використовуйтеMap
, явно призначене для цієї мети.
Якщо вам потрібно використовувати об'єкт, ES2017 (ES8) дозволяє вам використовувати Object.values
:
const foo = { a: 'foo', z: 'bar', m: 'baz' };
for (let value of Object.values(foo)) {
console.log(value);
}
Якщо це ще не підтримується, використовуйте polyfill: Альтернативна версія для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
може шляхом багаторазового заповнення, не торкаючись прототипу.
for-in
?
Ітератор, ітерабельний та 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 , тобто він повинен мати об'єкт із наступним методом. Наступний метод не бере аргументів, і він повинен повернути об'єкт із цими двома властивостями.
зроблено : сигнали , що послідовність закінчилася , коли істинно, і неправдиві кошти можуть бути більше значення значення : це поточний елемент в послідовності
Отже, зробити об’єкт ітерабельним , тобто змусити його працювати з for..of, ми можемо:
1. Зробіть об’єкт ітерувальним , призначивши йому властивість mystical @@ 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.Use 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({})) { }
Оскільки літерал об’єкта не має властивості Symbol.iterator . Якщо бути конкретним, ви можете перебирати лише рядки , масиви , карти , набори , аргументи , NodeList (не широко підтримується) та генератор за допомогою циклу for ... of .
Щоб мати справу з ітерацією об’єктного літералу, у вас є два варіанти.
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 призначений лише для ітерацій. У мене було точно таке саме запитання, оскільки я використовую Objects для перебору ключів і значень за допомогою for..in. Але я щойно зрозумів, що для цього призначені КАРТИ та НАБОРИ ES6 .
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])
}
Як щодо використання Object.keys для отримання масиву ключів? І тоді forEach на масиві ?
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"
поточний стан ітерації в bool.