Как получить все значения свойств объекта JavaScript (не зная ключей)?


455

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

var objects={...};

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


23
Примечание для читателей: не пропустите очень проницательный второй ответ
Pandaiolo

Ответы:


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 шайба

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


9
Это должен быть принятый (или, по крайней мере, более одобренный) ответ, поскольку принятый ответ является неполным (@olive указывает на это).
0xc0de

Обидно, что из всех так называемых уловок мы все равно должны упомянуть objдважды. Я думаю, создание вспомогательной функции неизбежно? Что-то вроде значений (obj).
Стивен Харьянто

Любой из этих методов может быть использован в качестве прокладки. Например:Object.values = obj => Object.keys(obj).map(key => obj[key]);
Кбайт

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.
Sandstrom

Зачем вам нужно проверить 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
lodash для этого не нужен и будет раздувать вашу кодовую базу
dman

14

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

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) прибыль!


3

ECMA2017 года:

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

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


Следует отметить, что это НЕ вернет унаследованные свойства.
Богатый Ремер

Это прекрасно работает .... Одна линия спасла мой день ....
Stack Kiddy

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]];
}

Можете ли вы поставить codepen или 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:


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));

По некоторым причинам values ​​() работает в 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

Я понимаю, что немного опаздываю, но вот прокладка для нового Object.valuesметода Firefox 47

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 Toolkit, потому что старые браузеры не поддерживают 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

Перейти к >> Консоль

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.