Питання Як прокручувати або перерахувати об'єкт JavaScript?


У мене є такий об'єкт JavaScript:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

Тепер я хочу співати через все p елементи (p1,p2,p3...) і отримати свої ключі та цінності. Як я можу це зробити?

Я можу змінити об'єкт JavaScript, якщо це необхідно. Моя кінцева мета полягає в тому, щоб спірити через деякі ключові значення пар і, якщо можливо, я хочу уникнути використання eval.


2133
2018-03-26 06:01


походження


Я змінював JSON на JavaScript (об'єкт), щоб уникнути заплутаності літературних об'єктів та JSON. - Felix Kling
Під час повторного збирання ви повинні дбати про оптимізацію. Оскільки це може вплинути на ефективність сторінки. - Zaheer Ahmed
Прекрасний друк Javascript:  j11y.io/demos/prettyprint  Я великий шанувальник функція скидання  ajaxian.com/archives/javascript-variable-dump-in-coldfusion - Kiquenet
функція dump:  github.com/ozmartian/js-cfdump - Kiquenet


Відповіді:


Ви можете скористатись for-in петля, як показали інші. Однак ви також повинні переконатися, що ключ, який ви отримуєте, є фактичною властивістю об'єкта, і не походить з прототипу.

Ось фрагмент:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

for (var key in p) {
    if (p.hasOwnProperty(key)) {
        console.log(key + " -> " + p[key]);
    }
}


3466
2018-03-26 06:12



Буде запропоновано змінити лінію попередження саме для чіткості alert(key + " -> " + JSON.stringify(p[key])); - Steve Midgley
Чи можете ви пояснити необхідність мати hasOwnProperty? Що ви маєте на увазі за прототипом? - kamaci
У JavaScript, у кожного об'єкта є купа вбудованих пар ключ-значення, які мають мета-інформацію. Коли ви циклу через всі пари ключових значень для об'єкта, який ви циклу через них теж. hasOwnPropery () фільтрує їх. - danieltalsky
Насправді Для ... в не є застарілим. Для кожного ... в є Але мені дуже подобається цей термін археологи... Я маю почати використовувати це. - Ben Y
кожен об'єкт у javascript (насправді, пара ключ-значення) має властивість, що викликається __proto__ або prototype. Ця властивість має посилання на її батьківський об'єкт. Об'єкт автоматично успадковує власність від свого батька. Це є причиною використання hasOwnProperty, що означає, що нас цікавлять об'єкти власної власності, а не їх батьківські. - Zubair Alam


Під ECMAScript 5 ви можете комбінувати Object.keys() і Array.prototype.forEach():

var obj = { first: "John", last: "Doe" };

Object.keys(obj).forEach(function(key) {
    console.log(key, obj[key]);
});

ES6 додає for...of:

for (const key of Object.keys(obj)) {
    console.log(key, obj[key]);
}

ES2017 додає Object.entries() що дозволяє уникнути пошуку кожного значення у вихідному об'єкті:

Object.entries(obj).forEach(
    ([key, value]) => console.log(key, value)
);

Обидва Object.keys() і Object.entries() повторювати властивості в тому ж порядку, що й а for...in петля але проігноруйте прототип ланцюга. Тільки перераховані властивості об'єкта повторюються.

Редагувати: ES2016 → ES6


627
2018-04-20 21:59



Чому стандарт не надавав Object.forEach(obj, function (value, key) {...})? :( Звичайно obj.forEach(function...) буде коротшим і доповнюватимуться Array.prototype.forEach, але це може спричинити ризик того, що об'єкти визначають власні forEach власність Я вважаю Object.keys охорона проти зворотного виклику, що змінює клавіші об'єкта. - David Harkness
Object.forEach = function (obj, callback) { Object.keys(obj).forEach(function (key) { callback(obj[key], key); }); } - David Harkness
@DavidHarkness Є в ES2017 Object.entries. Тут ви можете зробити наступне: Object.entries(obj).map/forEach(([key, value]) => console.log(key, value)) ([ключ, значення] - це деструкція масиву, щоб отримати доступ до обох елементів безпосередньо, а параметри потрібно загорнути у додаткових паролях.) - Andreas Linnert
як я можу отримати index ключ від JSON? Або, якщо потрібно, я повинен використовувати окремий лічильник? - Saravanabalagi Ramachandran
for...of є стандартом ES6, а не ES2016. - Rax Weber


Ви повинні використовувати для-в-петлі

Але будьте обережні, використовуючи цей тип циклу, тому що це буде петля всі властивості уздовж прототипу ланцюга.

Тому, коли використовуєте цикли for-in, завжди використовуйте hasOwnProperty метод, щоб визначити, чи поточний властивість в ітерації дійсно є властивістю об'єкта, який ви перевіряєте:

for (var prop in p) {
    if (!p.hasOwnProperty(prop)) {
        //The current property is not a direct property of p
        continue;
    }
    //Do your logic with the property here
}

300
2018-03-26 06:12



Це краще, ніж рішення Левіка, тому що це дозволяє основній логіці бути лише однією вкладеною петлею, а не два; що полегшує читання коду. Хоча я втратила брекети навколо продовження; вони зайві. - SystemicPlural
Я б не видалив { } особисто тому, що if без них робить трохи незрозумілим те, що є частиною if і що ні. Але я думаю, це лише питання думки :) - pimvdb
Так, я вважаю за краще зберегти { } головним чином, щоб уникнути плутанини, якщо пізніше потрібно додати щось до if обсяг - Andreas Grech
Читаючи мій попередній коментар, я зрозумів, що я не використовував правильні терміни, тому що я сказав "якщо сфера"; але майте на увазі, що JavaScript має лише область функцій. Тож я мав на увазі "якщо блок". - Andreas Grech
eomeroff, якщо ви дійсно стурбовані цим, ви завжди можете зробити щось на кшталт: Object.prototype.hasOwnProperty.call(p, prop)  Однак це теж не може захистити від маніпуляцій Object.prototype ... - jordancpaul


Питання не буде повним, якщо ми не згадуємо про альтернативні способи цитування через об'єкти.

На сьогоднішній день багато відомих бібліотек JavaScript надають власні методи для повторення над колекціями, тобто більше масиви, об'єкти, і масивні предмети. Ці методи зручні для використання і цілком сумісні з будь-яким браузером.

  1. Якщо ти працюєш jQuery, ви можете використовувати jQuery.each() метод Він може бути використаний для безперебійного ітерації над об'єктами та масивами:

    $.each(obj, function(key, value) {
        console.log(key, value);
    });
    
  2. В Underscore.js ви можете знайти метод _.each(), який повторюється над списком елементів, поступаючись кожен по черзі до функції, що постачається (зверніть увагу на порядок аргументів в ітерація функція!):

    _.each(obj, function(value, key) {
        console.log(key, value);
    });
    
  3. Lo-Dash надає кілька способів повторення властивостей об'єкта. Основний _.forEach() (або це псевдонім _.each()) корисний для циклічності через обидва об'єкти та масиви, однак (!) об'єкти з length властивість трактується як масиви, а для уникнення такої поведінки пропонується використовувати _.forIn() і _.forOwn() методи (у них теж є value аргумент прийшов спочатку):

    _.forIn(obj, function(value, key) {
        console.log(key, value);
    });
    

    _.forIn() повторюється власні та успадковані перелічені властивості об'єкта, в той час як _.forOwn() повторюється лише над власний властивості об'єкта (в основному перевірка проти hasOwnProperty функція) Для простих об'єктів та літературних об'єктів будь-який з цих методів буде працювати нормально.

Як правило, всі описані методи мають однакову поведінку з будь-якими поставленими об'єктами. Крім використання рідної for..in петля, як правило, буде швидше ніж будь-яка абстракція, наприклад jQuery.each(), ці методи значно простіше у використанні, вимагають меншого кодування та забезпечують кращу обробку помилок.


231
2018-01-20 17:58



Щоб дійти до значення: $ .each (obj, функція (ключ, значення) {console.log (value.title);}); - Ravi Ram
Просто весело, як підкреслити, і jquery змінили параметри :) - ppasler


У ECMAScript 5 у вас є новий підхід у полях ітерації буквально - Object.keys

Більше інформації ви можете побачити MDN

Мій вибір виглядає як більш швидке рішення в сучасних версіях веб-переглядачів (Chrome30, IE10, FF25).

var keys = Object.keys(p),
    len = keys.length,
    i = 0,
    prop,
    value;
while (i < len) {
    prop = keys[i];
    value = p[prop];
    i += 1;
}

Ви можете порівняти ефективність цього підходу з різними реалізаціями на jsperf.com:

Підтримка браузера ви можете побачити Комп'ютерний канал Kangax

Для старого браузера у вас є простий і повний поліфіль

UPD:

порівняння продуктивності для всіх найпопулярніших випадків у цьому питанні perfjs.info:

об'єкт літерна ітерація


47
2017-11-16 19:59



Дійсно, я просто хотів опублікувати цей метод. Але ти мене бив це :( - Jamie Hutber
jsperf.com/object-iteration- порівняння - Jason


Ви можете просто переглянути його, як:

for (var key in p) {
  alert(p[key]);
}

Зауважте, що key не візьме на себе вартість майна, це просто значення індексу.


30
2018-03-26 06:05



Це повторюється і навіть не цілком правильно. Для правильної роботи цієї роботи потрібно перевірити наявність hasOwnProperty - Vatsal


Оскільки es2015 стає все більш популярним, я розміщую цю відповідь, яка включає використання генератора та ітератора, щоб плавно ітерацію [key, value] пари Як це можливо на інших мовах, наприклад, Ruby.

Ось тут код:

const MyObject = {
  'a': 'Hello',
  'b': 'it\'s',
  'c': 'me',
  'd': 'you',
  'e': 'looking',
  'f': 'for',
  [Symbol.iterator]: function* () {
    for (const i of Object.keys(this)) {
      yield [i, this[i]];
    }
  }
};

for (const [k, v] of MyObject) {
  console.log(`Here is key ${k} and here is value ${v}`);
}

Вся інформація про те, як ви можете зробити ітератор і генератор, ви можете знайти на сторінці розробника Mozilla.

Сподіваюсь, це допомогло комусь.

EDIT:

ES2017 буде включати в себе Object.entries який буде робити повторення [key, value] пари в об'єктах ще простіше. В даний час відомо, що це буде частиною стандарту відповідно до ts39 інформаційна стадія.

Я думаю, що настав час оновити мою відповідь, щоб вона стала ще більш свіжою, ніж зараз.

const MyObject = {
  'a': 'Hello',
  'b': 'it\'s',
  'c': 'me',
  'd': 'you',
  'e': 'looking',
  'f': 'for',
};

for (const [k, v] of Object.entries(MyObject)) {
  console.log(`Here is key ${k} and here is value ${v}`);
}

Ви можете дізнатись більше про використання в MDN сторінка


24
2017-08-27 09:06



Дякую! тепер мої колеги не будуть знущатися над моїм стилем JS 2005 року! - the0ther
Це виглядає абсолютно зайвим / непотрібним для мене. Додати його до кожного об'єкта у вашій системі? Я думав, що пункт надання ітератора був таким, щоб ви могли зробити "for (const [k, v] of myObject"). Це просто виглядає як додатковий код, що має трохи додаткової вартості. - Dean Radcliffe


через прототип з для кожного() який повинен пропустити прототип ланцюга властивості:

Object.prototype.each = function(f) {
    var obj = this
    Object.keys(obj).forEach( function(key) { 
        f( key , obj[key] ) 
    });
}


//print all keys and values
var obj = {a:1,b:2,c:3}
obj.each(function(key,value) { console.log(key + " " + value) });
// a 1
// b 2
// c 3

17
2017-12-09 05:05



Будьте обережні з прототипом: obj = { print: 1, each: 2, word: 3 } випускає TypeError: number is not a function. Використовуючи forEach щоб відповідати подібним Arrayфункція може трохи знизити ризик. - David Harkness


Переглянувши всі відповіді тут, hasOwnProperty не потрібно для мого власного використання, тому що мій json об'єкт чистий; немає сенсу додати додаткову обробку JavaScript. Це все, що я використовую:

for (var key in p) {
    console.log(key + ' => ' + p[key]);
    // key is key
    // value is p[key]
}

14
2017-08-18 20:50



Незалежно від того, чи є об'єкт JSON чистим чи ні. Якщо в будь-який інший час деякий код встановлює властивість Object.prototype, то він буде перераховано на for..in. Якщо ви впевнені, що ви не використовуєте бібліотеки, які це роблять, вам не потрібно дзвонити hasOwnProperty. - G-Wiz
Це може бути повністю чистим, якщо його створити Object.create(null) - Juan Mendes


for(key in p) {
  alert( p[key] );
}

Примітка: ви можете зробити це за допомогою масивів, але ви будете ітерації над ними length та інші властивості теж.


14
2018-03-26 06:04



Коли ви використовуєте для циклу подібне, key просто візьме на себе значення індексу, так що буде просто попереджати 0, 1, 2 тощо ... Вам потрібно отримати доступ до p [ключ]. - Bryan
Це найповільніший метод ітерації масиву в JavaScript. Ви можете перевірити це на своєму комп'ютері - Найкращий спосіб повторити масиви в JavaScript - Pencroff
@Pencroff: проблема полягає в тому, що мова йде не про циклінг через масиви ...;) - Sk8erPeter
Це те, що я не розумію на stackoverflow. Річард дав правильну відповідь, і він був першим, хто давав відповідь, але він не отримав жодного +1? @ Брайан var p = {"p1":"q","p2":"w"}; for(key in p) { alert( key ); } з'являється в сповіщеннях "p1" і "p2", так що неправильно про це? - Sebastian
Я думаю, головна відмінність полягає в якості: інші відповіді не тільки розповідають, як, але також розповідають застереження (наприклад, прототип) та способи вирішення цих застережень. ІМХО, ці інші відповіді є краще мій :). - Richard Levasseur