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