Obtener un conjunto de claves de objeto

372

Me gustaría obtener las claves de un objeto JavaScript como una matriz, ya sea en jQuery o JavaScript puro.

¿Hay una forma menos detallada que esta?

var foo = { 'alpha' : 'puffin', 'beta' : 'beagle' };
var keys = [];
for (var key in foo) {
    keys.push(key);
}
Ricardo
fuente
44
Además de agregar if(foo.hasOwnProperty(key)), eso es lo que haría. O usar $.map.
Rocket Hazmat
10
Oh, para una línea Pythonic, aunque ...
Richard
una vieja pregunta, así que no merece una respuesta completa, pero para aquellos que quieren tocar el violín ... jsfiddle.net/LR5D9/3, esta solución trata el tema de las declaraciones de prototipos que desordenan los for var in xbucles
sincronizar el

Respuestas:

619

Uso 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).

Esta es una característica de ES5. Esto significa que funciona en todos los navegadores modernos, pero no funcionará en los navegadores heredados .

El ES5-shim tiene una implementación Object.keysque puedes robar

Raynos
fuente
55
Nota: Esto solo funciona en navegadores modernos (con eso quiero decir que no IE <9).
Rocket Hazmat
2
¿Y qué hay de los navegadores móviles?
Marwen Trabelsi
1
@SmartyTwiti: no estoy seguro. Supongo que funciona como Chrome o Firefox.
Rocket Hazmat
MDN también tiene el Polyfill mencionado anteriormente, pero observa errores en IE7 y quizás 8, luego se refiere a un Polyfill mucho más corto aquí: tokenposts.blogspot.com.au/2012/04/…
Campbeln
Entonces, ¿cómo se hizo esto antes de ES5?
Andrew S
59

Puedes usar jQuery's $.map.

var foo = { 'alpha' : 'puffin', 'beta' : 'beagle' },
keys = $.map(foo, function(v, i){
  return i;
});
Cohete Hazmat
fuente
O each, si estás haciendo algo con ellos. $.each(foo, function(index, value){/* do something with index */});
Chris
33

Por supuesto, Object.keys()es la mejor manera de obtener las claves de un Objeto. Si no está disponible en su entorno, se puede trivializar usando código como en su ejemplo (excepto que tendrá que tener en cuenta que su bucle iterará sobre todas las propiedades de la cadena del prototipo, a diferencia Object.keys()del comportamiento).

Sin embargo, su código de ejemplo ...

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

jsFiddle .

... podría ser modificado. Puede hacer la tarea directamente en la parte variable .

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

jsFiddle .

Por supuesto, este comportamiento es diferente de lo que Object.keys()realmente hace ( jsFiddle ). Simplemente puede usar la cuña en la documentación de MDN .

alex
fuente
8
Me gustó este var keys = [], i = 0; for (keys[i++] in foo) {}+1
Jashwant
Escuché que "for in" no garantiza el orden, ¿sabes si Object.keys sí?
Chris Stephens
@ChrisStephens Ninguno garantiza el orden, incluso si las claves terminan en una matriz ordenada.
alex
2
Todas estas soluciones necesitan un hasOwnProperty()cheque, ¿verdad?
sincronización
1
@TIMINeutron No hay ninguna razón por la que no debería :)
alex
7

No sé acerca de menos detallado, pero me inspiró para obligar a lo siguiente en una línea por la solicitud de una línea, sin embargo, no sé cuán pitónico es;)

var keys = (function(o){var ks=[]; for(var k in o) ks.push(k); return ks})(foo);
Dexygen
fuente
3
Quizás eso debería ser var enumerableKeysOnThePrototypeChain;)
alex
1
Tal vez somos lo suficientemente inteligentes como para saber que no tenemos que preocuparnos por hasOwnProperty si el objeto se crea completamente bajo nuestro alcance en lugar de ser importado de otro lugar
Dexygen
sin embargo, no es tan pitónico como la segunda respuesta de @ alex ( for (keys[i++] in foo) {}), porque todavía está realizando Array.push()(sin mencionar que declara una función completa). Una implementación pitónica debe basarse tanto en la comprensión implícita como sea posible, y en su defecto, utilizando una expresión lambda.
cowbert
4

En caso de que esté buscando algo para enumerar las claves de un objeto anidado de n profundidades como una matriz plana:

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

Cody Moniz
fuente
1

Resumen

Para obtener todas las claves de un Objeto que puede usar Object.keys(). Object.keys()toma un objeto como argumento y devuelve una matriz de todas las claves.

Ejemplo:

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

En el ejemplo anterior, almacenamos una matriz de claves en las claves const. Entonces podemos acceder fácilmente a la cantidad de propiedades en el objeto al verificar la longitud de la matriz de claves.

Obteniendo los valores con: Object.values()

La función complementaria de Object.keys()es Object.values(). Esta función toma un objeto como argumento y devuelve una matriz de valores. Por ejemplo:

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


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

Willem van der Veen
fuente
1

Si decides usar Underscore.js, será mejor que lo hagas

var foo = { 'alpha' : 'puffin', 'beta' : 'beagle' };
var keys = [];
_.each( foo, function( val, key ) {
    keys.push(key);
});
console.log(keys);
mohammad javad ahmadi
fuente