Как получить все значения свойств объекта Javascript (не зная ключей)? - PullRequest
429 голосов
/ 05 сентября 2011

Если есть объект Javascript:

var objects={...};

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

Ответы [ 20 ]

969 голосов
/ 20 мая 2013

В зависимости от того, какие браузеры вы должны поддерживать, это можно сделать несколькими способами. Подавляющее большинство браузеров в дикой природе поддерживают ECMAScript 5 (ES5), но имейте в виду, что во многих приведенных ниже примерах используется Object.keys, который недоступен в IE <9. См. Таблицу совместимости <a href="http://kangax.github.io/compat-table/es5/" rel="noreferrer"> .

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+ (A.K.A. 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 не может использоваться для создания частных свойств). Новый API Reflect из 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 шим

Наконец, как отмечено в комментариях и teh_senaus в другом ответе, возможно, стоит использовать один из них в качестве прокладки. Не волнуйтесь, следующее не меняет прототип, оно просто добавляет метод к 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, то у вас есть доступ ко всем функциям в этом ответе.

417 голосов
/ 05 сентября 2011

Используя простой цикл for..in:

for(var key in objects) {
    var value = objects[key];
}
30 голосов
/ 27 февраля 2013

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

Object.values = function (obj) {
    var vals = [];
    for( var key in obj ) {
        if ( obj.hasOwnProperty(key) ) {
            vals.push(obj[key]);
        }
    }
    return vals;
}
28 голосов
/ 08 августа 2013

Если у вас есть доступ к Underscore.js, вы можете использовать функцию _.values следующим образом:

_.values({one : 1, two : 2, three : 3}); // return [1, 2, 3]
14 голосов
/ 03 мая 2015

Если вам действительно нужен массив значений, я нахожу это чище, чем создание массива с циклом for ... in.

ECMA 5.1 +

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

Стоит отметить, что в большинстве случаев вам не нужен массив значений, это будет быстрее сделать это:

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

Это перебирает ключи Объекта o. В каждой итерации k имеет значение o.

9 голосов
/ 21 января 2015

ES5 Object.keys

var a = { a: 1, b: 2, c: 3 };
Object.keys(a).map(function(key){ return a[key] });
// result: [1,2,3]
5 голосов
/ 05 сентября 2011

Вы можете переключаться между клавишами:

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
3 голосов
/ 24 февраля 2015

Для тех, кто рано адаптировался к эпохе CofeeScript, вот еще один аналог.

val for key,val of objects

Что может быть лучше, чем это, потому что objects может быть уменьшено для повторного ввода и уменьшена читаемость.

objects[key] for key of objects
3 голосов
/ 26 декабря 2015

используйте полифилл как:

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

затем используйте

Object.values(my_object)

3) прибыль!

2 голосов
/ 04 июля 2018

ECMA2017 года:

Object.values(obj) извлечет все значения свойств в виде массива.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Object/values

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...