Як отримати всі значення властивостей об’єкта JavaScript (не знаючи ключів)?


455

Якщо є об’єкт Javascript:

var objects={...};

Припустимо, у нього більше 50 властивостей, не знаючи імен властивостей (це не знаючи "клавіш"), як отримати кожне значення властивості в циклі?


23
Зауважте читачам: не пропустіть дуже проникливу другу відповідь
Пандайоло

Відповіді:


447

Використовуючи просту for..inпетлю:

for(var key in objects) {
    var value = objects[key];
}

90
Будьте уважні до властивостей об'єкта-прототипу, що передається у спадок. Дивіться: hasOwnProperty ()
оливкова

102
Якщо ви читаєте цю відповідь, вам обов’язково слід прочитати іншу
mgarciaisaia

18
Якщо ви читаєте цю відповідь, і, можливо, ви стикаєтесь з рядками, вам обов'язково слід вдарити javascript у обличчя.

Якщо ви читаєте вищезгадану відповідь і хочете вдарити JavaScript обличчям, спробуйте lodash
slugmandrew

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

1012

Залежно від того, які браузери потрібно підтримувати, це можна зробити різними способами. Переважна більшість браузерів у дикій природі підтримує ECMAScript 5 (ES5), але слід попередити, що багато з наведених нижче прикладів використовують Object.keys, чого немає в IE <9. Див. Таблицю сумісності .

ECMAScript 3+

Якщо вам доведеться підтримувати старіші версії IE, то для вас це варіант:

for (var key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
        var val = obj[key];
        // use val
    }
}

Вкладене ifгарантує, що ви не перераховуєте властивості в прототипі ланцюга об'єкта (такої поведінки ви майже напевно хочете). Ви повинні використовувати

Object.prototype.hasOwnProperty.call(obj, key) // ok

а не

obj.hasOwnProperty(key) // bad

тому що ECMAScript 5+ дозволяє створювати об'єкти Object.create(null), що не мають прототипу , і цей об'єкт не матиме hasOwnPropertyметоду. Неслухняний код також може створювати об'єкти, які перекривають hasOwnPropertyметод.

ECMAScript 5+

Ви можете використовувати ці методи в будь-якому браузері, що підтримує ECMAScript 5 і вище. Вони отримують значення від об'єкта і уникають перерахування по прототипу ланцюга. Де objваш об’єкт:

var keys = Object.keys(obj);

for (var i = 0; i < keys.length; i++) {
    var val = obj[keys[i]];
    // use val
}

Якщо ви хочете щось більш компактне або хочете бути обережними з функціями в циклі, то Array.prototype.forEachваш друг:

Object.keys(obj).forEach(function (key) {
    var val = obj[key];
    // use val
});

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

var vals = Object.keys(obj).map(function (key) {
    return obj[key];
});

// use vals array

Якщо ви хочете зробити тих, хто використовує Object.keysбезпеку проти null(як for-inє), тоді ви можете зробити Object.keys(obj || {})....

Object.keysповертає численні властивості. Для ітерації над простими об'єктами зазвичай цього достатньо. Якщо у вас є щось з незліченними властивостями, з якими вам потрібно працювати, ви можете використовувати Object.getOwnPropertyNamesзамість цього Object.keys.

ECMAScript 2015+ (AKA ES6)

Масиви простіші в ітерації з ECMAScript 2015. Ви можете використовувати це з користю для роботи зі значеннями один за одним в циклі:

for (const key of Object.keys(obj)) {
    const val = obj[key];
    // use val
}

Використовуючи функції ECMAScript 2015 жирної стрілки, відображення об'єкта в масив значень стає однолінійним:

const vals = Object.keys(obj).map(key => obj[key]);

// use vals array

ECMAScript 2015 представляє Symbol, екземпляри яких можуть використовуватися як імена властивостей. Щоб отримати символи об'єкта для перерахунку, використовуйте Object.getOwnPropertySymbols(ця функція є причиноюSymbol не можна використовувати для створення приватних властивостей). Новий ReflectAPI від ECMAScript 2015 надаєReflect.ownKeys , який повертає список імен властивостей (включаючи не перелічувані) та символи.

Масив розуміння (не намагайтеся використовувати)

Поняття масиву були видалені з ECMAScript 6 перед публікацією. До їх вилучення рішення виглядало б так:

const vals = [for (key of Object.keys(obj)) obj[key]];

// use vals array

ECMAScript 2017+

ECMAScript 2016 додає функції, які не впливають на цю тему. Специфікація ECMAScript 2017 додає Object.valuesта Object.entries. Обидва повертають масиви (що для деяких буде дивовижно за аналогією з Array.entries). Object.valuesможна використовувати як є, так і з for-ofпетлею.

const values = Object.values(obj);

// use values array or:

for (const val of Object.values(obj)) {
    // use val
}

Якщо ви хочете використовувати як ключ, так і значення, то Object.entriesдля вас. Він створює масив, заповнений [key, value]парами. Ви можете використовувати це як є, або (зверніть увагу також на завдання деструктування ECMAScript 2015) у for-ofциклі:

for (const [key, val] of Object.entries(obj)) {
    // use key and val
}

Object.values шим

Нарешті, як зазначається в коментарях та тех_сенаусом в іншій відповіді, можливо, варто використати один із них як прокладку. Не хвилюйтесь, наступне не змінює прототип, воно просто додає метод Object(що набагато менш небезпечно). Використовуючи функції жирової стрілки, це можна зробити і в одному рядку:

Object.values = obj => Object.keys(obj).map(key => obj[key]);

якими ви зараз можете користуватися

// ['one', 'two', 'three']
var values = Object.values({ a: 'one', b: 'two', c: 'three' });

Якщо ви хочете уникнути мерехтіння, коли Object.valuesіснує рідний , ви можете зробити:

Object.values = Object.values || (obj => Object.keys(obj).map(key => obj[key]));

Нарешті ...

Будьте в курсі браузерів / версій, які вам потрібно підтримувати. Вищезгадане є правильним там, де реалізовані методи або особливості мови. Наприклад, до недавнього часу підтримка ECMAScript 2015 була вимкнена за замовчуванням у V8, яка використовувала такі браузери, як Chrome. Особливостей ECMAScript 2015 слід уникати, поки браузери, які ви збираєтесь підтримувати, не реалізують необхідні функції. Якщо ви використовуєте babel для складання свого коду до ECMAScript 5, то у вас є доступ до всіх функцій у цій відповіді.


9
Це має бути прийнятою (або принаймні більш вигідною) відповіддю, оскільки прийнята є неповною (@olive балів це).
0xc0de

Прикро, що про всі так звані трюки нам ще потрібно згадати objдвічі. Гадаю, створення функції помічника неминуче? Щось на зразок значень (obj).
Стівен Хар'янто

Будь-який із цих методів може бути використаний як шим. Наприклад:Object.values = obj => Object.keys(obj).map(key => obj[key]);
qubyte

1
Рішення ECMA 5 повинні працювати у всіх сучасних браузерах. ECMA 6 ще не було завершено, і підтримка є попередньою у всіх браузерах. У Chrome, ECMA 6 частково реалізований, але відключений. У Firefox підтримка краща, але розуміння масиву неправильне (як уже згадувалося). Я думав, що моє використання майбутнього часу означатиме це. @JacekLampart, яке рішення дало вам помилку?
квабайт

2
Я не уявляю, чому нам доведеться чекати ES2017, щоб отримати метод Object.values ​​().
Гербертуш

31

Ось функція багаторазового використання для отримання значень у масив. Він також враховує прототипи.

Object.values = function (obj) {
    var vals = [];
    for( var key in obj ) {
        if ( obj.hasOwnProperty(key) ) {
            vals.push(obj[key]);
        }
    }
    return vals;
}

15
Модифікація Objectне є великою проблемою ( Object.keysце звичайна лайка), ви, напевно, думаєте про зміну прототипу Object.
пісок

Навіщо вам потрібно тестуватися hasOwnProperty()? Як би ітератор ключа в циклі цього об'єкта не мав властивості?
1252748

4
Google це @ thomas, це важливо. Він може мати властивості своєї прототипу.
Джо

28

Якщо у вас є доступ до Underscore.js, ви можете скористатися такою _.valuesфункцією:

_.values({one : 1, two : 2, three : 3}); // return [1, 2, 3]

@MathieuAmiot - хочете пояснити?
Паден

lodash - це сумісна з api заміна для підкреслення, (шлях) швидшого.
Матьє Аміот

@Paden ось пов'язаний з цим питання про SO: stackoverflow.com/questions/13789618 / ...
Jichi

2
Лодаш для цього непотрібний, і
пошкодить

14

Якщо ви дійсно хочете масив Значення, я вважаю це чистішим, ніж будувати масив з циклом для ... у циклі.

ECMA 5.1+

function values(o) { return Object.keys(o).map(function(k){return o[k]}) }

Варто зазначити, що в більшості випадків вам не потрібен масив значень, це буде швидше зробити:

for(var k in o) something(o[k]);

Це повторюється над клавішами Object o. У кожній ітерації k встановлюється ключ o.


9

ES5 Object.keys

var a = { a: 1, b: 2, c: 3 };
Object.keys(a).map(function(key){ return a[key] });
// result: [1,2,3]

3
Чому це було знято? Я б сказав, що це одне з найчистіших рішень.
Себастьян Ходжас

Я не знаю, чому за це проголосували. Це найпростіше та найчистіше рішення у js, не використовуючи жодних бібліотек чи будь-яких інших утиліт.
sanjeev shetty

5

Ви можете провести цикл через клавіші:

foo = {one:1, two:2, three:3};
for (key in foo){
    console.log("foo["+ key +"]="+ foo[key]);
}

виведе:

foo[one]=1
foo[two]=2
foo[three]=3

2
Вам також потрібно перевірити `hasOwnProperty () ', якщо ви хочете уникнути успадкованих атрибутів.
0xc0de

3

Для тих, хто рано адаптується до людей в епоху CofeeScript, ось ще один еквівалент цього.

val for key,val of objects

Що може бути краще, ніж це, тому що objectsможна зменшити, щоб знову набрати та зменшити читабельність.

objects[key] for key of objects

3

використовувати поліфункцію типу:

if(!Object.values){Object.values=obj=>Object.keys(obj).map(key=>obj[key])}

потім використовувати

Object.values(my_object)

3) прибуток!



2

Мабуть - як я нещодавно дізнався - це найшвидший спосіб зробити це:

var objs = {...};
var objKeys = Object.keys(obj);
for (var i = 0, objLen = objKeys.length; i < objLen; i++) {
    // do whatever in here
    var obj = objs[objKeys[i]];
}

чи можете ви прикласти коден або jsfiddle з прикладу цього? Дякую.
Chris22

2

Питання не визначає, чи бажають також успадковані та не перелічені властивості.

Існує питання, як отримати все, успадковані властивості та не перелічені властивості , які Google не може легко знайти.

Моє рішення для цього:

function getAllPropertyNames(obj) {
    let result = new Set();
    while (obj) {
        Object.getOwnPropertyNames(obj).forEach(p => result.add(p));
        obj = Object.getPrototypeOf(obj);
    }
    return [...result];
}

А потім перегляньте їх, просто використовуйте цикл for-of:


1

Використання:, Object.values()ми передаємо об’єкт як аргумент і отримуємо масив значень як зворотне значення.

Це повертає масиву даного об'єкта власні перелічені значення властивостей. Ви отримаєте ті самі значення, що і за допомогою for inциклу, але без властивостей прототипу. Цей приклад, ймовірно, зробить речі зрозумілішими:

function person (name) {
  this.name = name;
}

person.prototype.age = 5;

let dude = new person('dude');

for(let prop in dude) {
  console.log(dude[prop]);     // for in still shows age because this is on the prototype
}                              // we can use hasOwnProperty but this is not very elegant

// ES6 + 
console.log(Object.values(dude));
// very concise and we don't show props on prototype


1
const object1 = {
  a: 'somestring',
  b: 42
};

for (let [key, value] of Object.entries(object1)) {
  console.log(`${key}: ${value}`);
}

// expected output:
// "a: somestring"
// "b: 42"
// order is not guaranteed

0

Ось функція, схожа на PHP-файл array_values ​​()

function array_values(input) {
  var output = [], key = '';
  for ( key in input ) { output[output.length] = input[key]; }
  return output;
}

Ось як отримати значення об'єкта, якщо ви використовуєте ES6 або вище:

Array.from(values(obj));

Чомусь значення () працюють у Chrome та Firefox, але не у iojs / node.
jaggedsoft

0

Сумісний з ES7, навіть деякі браузери його ще не підтримують

Оскільки, Object.values(<object>)буде вбудовано в ES7 &

Дочекавшись, коли всі браузери його підтримають, ви можете зафіксувати його всередині функції:

Object.vals=(o)=>(Object.values)?Object.values(o):Object.keys(o).map((k)=>o[k])

Тоді :

Object.vals({lastname:'T',firstname:'A'})
 // ['T','A']

Як тільки браузери стануть сумісними з ES7, вам не доведеться нічого змінювати у своєму коді.


0

Я розумію , що я трохи пізно , але ось прокладка нового світлячок 47 Object.valuesметоду

Object.prototype.values = Object.prototype.values || function(obj) {
  return this.keys(obj).map(function(key){
    return obj[key];
  });
};

0

Object.entries роблять це краще.

  var dataObject = {"a":{"title":"shop"}, "b":{"title":"home"}}
 
   Object.entries(dataObject).map(itemArray => { 
     console.log("key=", itemArray[0], "value=", itemArray[1])
  })


0

const myObj = { a:1, b:2, c:3 }

Отримати всі значення:

  • найкоротший шлях:

    • const myValues = Object.values(myObj)
  • const myValues = Object.keys(myObj).map(key => myObj[key])


-1
var objects={...}; this.getAllvalues = function () {
        var vls = [];
        for (var key in objects) {
            vls.push(objects[key]);
        }
        return vls;
    }

-5

у використанні ECMAScript5

 keys = Object.keys(object);

Інакше, якщо ваш браузер не підтримує це, використовуйте відоме for..in loop

for (key in object) {
    // your code here
}

17
Питання полягало в тому, щоб задавати значення, а не ключі.
зачелрат

@zachelrath Ви маєте рацію. - Але цей скрипт корисний, якщо ви хочете отримати значення, тому що, коли ви знаєте ключі, ви можете використовувати їх object[key]для отримання значень у циклі.
fridojet

2
@fridojet Але це можна зробити за допомогою for..in(і hasOwnProperty), тому він насправді нічого не отримує .. Я хотів би, щоб ECMAScript 5-й визначений Object.pairsObject.itemsдля [[key, value], ..]), але на жаль, це не так.
user2246674

-8

Зараз я використовую інструментарій Dojo, оскільки старші веб-переглядачі не підтримують Object.values.

require(['dojox/lang/functional/object'], function(Object) {
    var obj = { key1: '1', key2: '2', key3: '3' };
    var values = Object.values(obj);
    console.log(values);
});

Вихід:

['1', '2', '3']

5
Строго кажучи, масив невірний. У вас є масив рядків замість масиву чисел.
квіте

-10

використання

console.log(variable)

а якщо ви використовуєте google chrome, відкрийте консоль за допомогою Ctrl + Shift + j

Goto >> Консоль

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.