¿Cómo encontrar las claves de un hash?

192

Sé que en JavaScript los objetos se duplican como hashes, pero no he podido encontrar una función integrada para obtener las claves

var h = {a:'b',c:'d'};

Quiero algo como

var k = h.keys() ; // k = ['a','c'];

Es simple escribir una función para iterar sobre los elementos y agregar las claves a una matriz que devuelvo, pero ¿hay una forma estándar más limpia de hacerlo?

Sigo sintiendo que debe ser una función incorporada simple que me perdí, ¡pero no puedo encontrarla!

Palmadita
fuente
Solo estoy saltando a JavaScript, pero esta publicación puede ayudarte. dean.edwards.name/weblog/2006/07/enum
jason saldo
Posible duplicado de Obtener matriz de claves de objeto
blo0p3r
1
¿Qué hay de obtener los valores de las claves? Además, obtener el número de claves en un hash.
zero_cool
La respuesta de 2017: Object.keys (h) Object.values ​​(h)
perdido

Respuestas:

274

Hay una función en JavaScript moderno (ECMAScript 5) llamada Object.keysrealizar esta operación:

var obj = { "a" : 1, "b" : 2, "c" : 3};
alert(Object.keys(obj)); // will output ["a", "b", "c"]

Los detalles de compatibilidad se pueden encontrar aquí .

En el sitio de Mozilla también hay un fragmento de compatibilidad con versiones anteriores:

if(!Object.keys) Object.keys = function(o){
   if (o !== Object(o))
      throw new TypeError('Object.keys called on non-object');
   var ret=[],p;
   for(p in o) if(Object.prototype.hasOwnProperty.call(o,p)) ret.push(p);
   return ret;
}
Ivan Nevostruev
fuente
¿No habría sido esto más natural? if(!Object.prototype.keys) Object.prototype.keys = function() { if (this !== Object(this)) throw new TypeError('Object.keys called on non-object'); var ret = [], p; for (p in this) if (Object.prototype.hasOwnProperty.call(this, p)) ret.push(p); return ret; } var x = { a: { A: 1, B: 2, C: 3 }, b: { A: 10, B: 20 } }; alert(x.a.keys());
ekkis
2
Según tengo entendido, esto Object.prototype.keysestará keysdisponible para todas las subclases de Object, por lo tanto, para todos los objetos. Lo que probablemente quieras si estás tratando de usar OOP. De todos modos, esto realmente depende de sus requisitos.
Ivan Nevostruev
1
Si usa mootools, Object.keys () debería estar disponible en todos los navegadores.
thepeer
¿Hay algo para usar esto en plantillas angulares? No funciona allí dentro de parciales.
Jay Shukla
Creo que deberías hacer esto como una pregunta separada con muestra de código.
Ivan Nevostruev
80

Para el código de producción que requiere una gran compatibilidad con los navegadores de clientes, sigo sugiriendo la respuesta de Ivan Nevostruev anterior con una cuña para garantizar Object.keysen los navegadores más antiguos. Sin embargo, es posible obtener la funcionalidad exacta solicitada utilizando la nueva definePropertyfunción de ECMA .

A partir de ECMAScript 5 - Object.defineProperty

A partir de ECMA5 puede usar Object.defineProperty()para definir propiedades no enumerables. La compatibilidad actual todavía tiene mucho que desear, pero eventualmente debería ser utilizable en todos los navegadores. (¡Tenga en cuenta específicamente la incompatibilidad actual con IE8!)

Object.defineProperty(Object.prototype, 'keys', {
  value: function keys() {
    var keys = [];
    for(var i in this) if (this.hasOwnProperty(i)) {
      keys.push(i);
    }
    return keys;
  },
  enumerable: false
});

var o = {
    'a': 1,
    'b': 2
}

for (var k in o) {
    console.log(k, o[k])
}

console.log(o.keys())

# OUTPUT
# > a 1
# > b 2
# > ["a", "b"]

Sin embargo, dado que ECMA5 ya se agregó, Object.keystambién podría usar:

Object.defineProperty(Object.prototype, 'keys', {
  value: function keys() {
    return Object.keys(this);
  },
  enumerable: false
});

Respuesta original

Object.prototype.keys = function ()
{
  var keys = [];
  for(var i in this) if (this.hasOwnProperty(i))
  {
    keys.push(i);
  }
  return keys;
}

Editar: dado que esta respuesta ha estado presente por un tiempo, dejaré la anterior sin tocar. Cualquiera que lea esto también debería leer la respuesta de Ivan Nevostruev a continuación.

No hay forma de hacer que las funciones prototipo no sean enumerables, lo que hace que siempre aparezcan en bucles for-in que no se usan hasOwnProperty. Todavía creo que esta respuesta sería ideal si extender el prototipo de Object no fuera tan complicado.

AnnanFay
fuente
9
'hasOwnProperty' excluye propiedades en los prototipos de este objeto, lo cual es útil saber.
ijw
2
Respuesta aceptada porque así es como terminé implementándola, pero siento que esto debería haber sido una función incorporada del lenguaje.
Pat
55
Tenga en cuenta que debe usar "for (var i in this) ..." para evitar crear una variable global.
Brad G.
55
Evitaría modificar Object.prototype: como otro comentarista señala a continuación, esto puede romper fácilmente los scripts que no tienen cuidado al verificar hasOwnProperty (). En su lugar, use la forma menos amigable para OO: defina una función de 'teclas' si aún no existe. (Firefox y Chrome implementan una función de teclas nativas () que hace exactamente lo que el OP quiere - IE no)
digitalbath
1
Parece una mala idea agregar algo al Object.prototype, ya que rompe todos los bucles normales como: for (var k in array) {} o for (var k in object), y ese idioma, aunque puede ser defectuoso - Es extremadamente común. Por ejemplo, según la respuesta de Matthew Darwin a continuación, rompe Google Maps.
Sam Watkins,
42

puedes usar Object.keys

Object.keys(h)
Leticia Santos
fuente
3
Se agregó en ECMAScript 5, pero ya debería funcionar en la mayoría de los navegadores principales
Pat
33

Puede usar Underscore.js , que es una biblioteca de utilidades de Javascript.

_.keys({one : 1, two : 2, three : 3}); 
// => ["one", "two", "three"]
timotti
fuente
Bueno, en realidad no es lo que se pedía, porque @Pat está buscando una función integrada de, pero es una interesante biblioteca, sin embargo, y no modificaObject.prototype
fresskoma
2
En estos días, creo que es mucho más útil usar estas pequeñas bibliotecas ingeniosas que seguir escribiendo sus propias implementaciones ... De todos modos, en la mayoría de los proyectos del mundo real, de todos modos estamos utilizando Underscore o bibliotecas equivalentes. Personalmente, prefiero ir con Underscore.
kumarharsh
_.keys(obj).lengthpara ver si hay alguna llave.
chovy
13

Esto es lo mejor que puedes hacer, que yo sepa ...

var keys = [];
for (var k in h)keys.push(k);
danb
fuente
2
Esto tampoco funciona cuando Object.prototype ha sido alterado.
Phil
44
Sería mejor usar esto, y no "meterse con" Object.prototype. Parece que todo se rompe si agregamos cosas a Object.prototype: es un lenguaje extremadamente común recorrer las teclas de una matriz / objeto.
Sam Watkins,
8

usando jQuery puede obtener las claves de esta manera:

var bobject =  {primary:"red",bg:"maroon",hilite:"green"};
var keys = [];
$.each(bobject, function(key,val){ keys.push(key); });
console.log(keys); // ["primary", "bg", "hilite"]

O:

var bobject =  {primary:"red",bg:"maroon",hilite:"green"};
$.map(bobject, function(v,k){return k;});

gracias a @pimlottc

chim
fuente
3
Si quisieras seguir esta ruta, también podrías usar JQuery.map: $.map(h, function(v,k) { return k; });
pimlottc
6

Creo que puede recorrer las propiedades del objeto usando for / in, por lo que podría hacer algo como esto:

function getKeys(h) {
  Array keys = new Array();
  for (var key in h)
    keys.push(key);
  return keys;
}
palmsey
fuente
4

Quería usar la respuesta mejor calificada arriba

Object.prototype.keys = function () ...

Sin embargo, cuando se usa junto con la API de Google Maps v3, Google Maps no es funcional.

for (var key in h) ...

funciona bien.

Matthew Darwin
fuente
1

si está tratando de obtener solo los elementos pero no las funciones, entonces este código puede ayudarlo

this.getKeys = function() {

var keys = new Array();
for(var key in this) {

    if( typeof this[key] !== 'function') {

        keys.push(key);
    }
}
return keys;

}

esto es parte de mi implementación de HashMap y solo quiero las claves, thises el objeto hashmap que contiene las claves

zeacuss
fuente