Получить массив ключей объекта

372

Я хотел бы получить ключи объекта JavaScript в виде массива, либо в jQuery, либо в чистом JavaScript.

Есть ли менее многословный способ, чем этот?

var foo = { 'alpha' : 'puffin', 'beta' : 'beagle' };
var keys = [];
for (var key in foo) {
    keys.push(key);
}
Ричард
источник
4
Помимо добавления if(foo.hasOwnProperty(key)), это то, что я бы сделал. Или используйте $.map.
Ракета Хазмат
10
О, для питонского однострочного, хотя ...
Ричард
старый вопрос, который не заслуживает полного ответа, но для тех, кто хочет поиграть ... jsfiddle.net/LR5D9/3 это решение имеет дело с проблемой объявления прототипов, путающихся в for var in xциклах
несинхронизировано

Ответы:

619

Используйте Object.keys:

var foo = {
  'alpha': 'puffin',
  'beta': 'beagle'
};

var keys = Object.keys(foo);
console.log(keys) // ['alpha', 'beta'] 
// (or maybe some other order, keys are unordered).

Это особенность ES5. Это означает, что он работает во всех современных браузерах, но не будет работать в старых браузерах .

ES5-шим имеет реализацию Object.keysвы можете украсть

Raynos
источник
5
Примечание. Это работает только в современных браузерах (я имею в виду не IE <9).
Ракета Хазмат
2
А как насчет мобильных браузеров?
Марвен Трабелси
1
@SmartyTwiti: я не уверен. Я предполагаю, что это как в Chrome или Firefox.
Ракетный Хазмат
MDN также имеет упомянутый выше Polyfill, но отмечает ошибки в IE7 и, возможно, 8, а затем ссылается на гораздо более короткий Polyfill здесь: tokenposts.blogspot.com.au/2012/04/…
Campbeln
Так как же сделать это до ES5?
Эндрю С
59

Вы можете использовать JQuery $.map.

var foo = { 'alpha' : 'puffin', 'beta' : 'beagle' },
keys = $.map(foo, function(v, i){
  return i;
});
Ракета Хазмат
источник
Или each, если вы что-то делаете с ними. $.each(foo, function(index, value){/* do something with index */});
Крис
33

Конечно, Object.keys()это лучший способ получить ключи Объекта. Если он не доступен в вашей среде, это может быть тривиальным подкладками с помощью кода , например , как в вашем примере ( за исключением вы должны принять во внимание ваш цикл будет перебрать все свойства в цепочке прототипов, в отличие от Object.keys()поведения «s).

Тем не менее, ваш пример кода ...

var foo = { 'alpha' : 'puffin', 'beta' : 'beagle' };
var keys = [];
for (var key in foo) {
    keys.push(key);
}

jsFiddle .

... может быть изменено. Вы можете сделать назначение прямо в переменной части.

var foo = { 'alpha' : 'puffin', 'beta' : 'beagle' };
var keys = [], i = 0;
for (keys[i++] in foo) {}

jsFiddle .

Конечно, это поведение отличается от того, что на Object.keys()самом деле ( jsFiddle ). Вы можете просто использовать прокладку в документации MDN .

Алекс
источник
8
Мне понравилось var keys = [], i = 0; for (keys[i++] in foo) {}+1
Jashwant
Я слышал, что "for in" не гарантирует порядок, вы знаете, если Object.keys делает?
Крис Стивенс
@ChrisStephens Не гарантирует порядок, даже если ключи оказываются в упорядоченном массиве.
Алекс
2
все эти решения нуждаются в hasOwnProperty()проверке, конечно?
несинхронизировано
1
@TIMINeutron Нет причин, почему это не следует :)
alex
7

Я не знаю о менее многословном, но я был вдохновлен привести следующее к одной строке запросом одной строки, хотя не знаю, насколько Pythonic это;)

var keys = (function(o){var ks=[]; for(var k in o) ks.push(k); return ks})(foo);
Dexygen
источник
3
Может быть, так и должно быть var enumerableKeysOnThePrototypeChain;)
alex
1
Может быть, мы достаточно умны, чтобы знать, что нам не нужно беспокоиться о hasOwnProperty, если объект создан полностью под нашей компетенцией, а не импортирован откуда-то еще
Dexygen
не такой питонический, как второй ответ @ alex ( for (keys[i++] in foo) {}), потому что вы все еще выполняете Array.push()(не говоря уже об объявлении всей функции). Питонная реализация должна полагаться как можно больше на неявное понимание, а если оно не удастся, используя лямбда-выражение.
Cowbert
4

В случае, если вы ищете что-то, чтобы перечислить ключи вложенного объекта n-глубины в виде плоского массива:

const getObjectKeys = (obj, prefix = '') => {
  return Object.entries(obj).reduce((collector, [key, val]) => {
    const newKeys = [ ...collector, prefix ? `${prefix}.${key}` : key ]
    if (Object.prototype.toString.call(val) === '[object Object]') {
      const newPrefix = prefix ? `${prefix}.${key}` : key
      const otherKeys = getObjectKeys(val, newPrefix)
      return [ ...newKeys, ...otherKeys ]
    }
    return newKeys
  }, [])
}

console.log(getObjectKeys({a: 1, b: 2, c: { d: 3, e: { f: 4 }}}))

Коди Мониз
источник
1

Резюме

Для получения всех ключей объекта вы можете использовать Object.keys(). Object.keys()принимает объект в качестве аргумента и возвращает массив всех ключей.

Пример:

const object = {
  a: 'string1',
  b: 42,
  c: 34
};

const keys = Object.keys(object)

console.log(keys);

console.log(keys.length) // we can easily access the total amount of properties the object has

В приведенном выше примере мы храним массив ключей в ключах const. Затем мы можем легко получить доступ к количеству свойств объекта, проверив длину массива ключей.

Получение значений с помощью: Object.values()

Дополнительной функцией Object.keys()является Object.values(). Эта функция принимает объект в качестве аргумента и возвращает массив значений. Например:

const object = {
  a: 'random',
  b: 22,
  c: true
};


console.log(Object.values(object));

Виллем ван дер Веен
источник
1

Если вы решили использовать Underscore.js, лучше

var foo = { 'alpha' : 'puffin', 'beta' : 'beagle' };
var keys = [];
_.each( foo, function( val, key ) {
    keys.push(key);
});
console.log(keys);
Мохаммад Джавад Ахмади
источник