Comment trouver les clés d'un hash?

193

Je sais que les objets javascript servent de hachage, mais je n'ai pas pu trouver de fonction intégrée pour obtenir les clés

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

Je veux quelque chose comme

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

Il est simple d'écrire moi-même une fonction pour parcourir les éléments et ajouter les clés à un tableau que je retourne, mais y a-t-il un moyen plus propre de le faire?

Je continue à penser que ce doit être une simple fonction intégrée qui m'a manqué mais je ne la trouve pas!

Tapoter
la source
Je me lance juste dans le javascript, mais cet article peut vous aider. dean.edwards.name/weblog/2006/07/enum
jason saldo
1
Double
1
Qu'en est-il d'obtenir les valeurs des clés? En outre, obtenir le nombre de clés dans un hachage.
zero_cool
La réponse 2017: Object.keys (h) Object.values ​​(h)
losty

Réponses:

277

Il existe une fonction en JavaScript moderne (ECMAScript 5) appelée à Object.keyseffectuer cette opération:

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

Les détails de compatibilité peuvent être trouvés ici .

Sur le site Mozilla, il existe également un extrait de code de compatibilité descendante:

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
la source
cela n'aurait-il pas été plus naturel? 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
Si je comprends bien, cela Object.prototype.keysrendra keysdisponible à toutes les sous-classes d'objets, donc pour tous les objets. Ce que vous voudrez probablement si vous essayez d'utiliser la POO. Quoi qu'il en soit, cela dépend vraiment de vos besoins.
Ivan Nevostruev du
1
Si vous utilisez mootools, Object.keys () devrait être disponible dans tous les navigateurs.
thepeer
Y a-t-il quelque chose à utiliser dans les modèles angulaires? Son ne fonctionne pas là à l'intérieur des partiels.
Jay Shukla
Je pense que vous devriez poser cette question séparément avec un exemple de code.
Ivan Nevostruev
80

Pour le code de production nécessitant une grande compatibilité avec les navigateurs clients, je suggère toujours la réponse d'Ivan Nevostruev ci-dessus avec shim pour garantir Object.keysdans les navigateurs plus anciens. Cependant, il est possible d'obtenir la fonctionnalité exacte demandée en utilisant la nouvelle definePropertyfonctionnalité d' ECMA .

À partir d'ECMAScript 5 - Object.defineProperty

Depuis ECMA5, vous pouvez utiliser Object.defineProperty()pour définir des propriétés non énumérables. La compatibilité actuelle a encore beaucoup à désirer, mais cela devrait éventuellement devenir utilisable dans tous les navigateurs. (Notez en particulier l'incompatibilité actuelle avec 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"]

Cependant, puisque ECMA5 a déjà été ajouté, Object.keysvous pouvez également utiliser:

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

Réponse originale

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

Edit: Puisque cette réponse existe depuis un certain temps, je laisserai ce qui précède intact. Quiconque lit ceci devrait également lire la réponse d'Ivan Nevostruev ci-dessous.

Il n'y a aucun moyen de rendre les fonctions de prototype non énumérables, ce qui les conduit toujours à apparaître dans des boucles d'entrée qui ne sont pas utilisées hasOwnProperty. Je pense toujours que cette réponse serait idéale si l'extension du prototype d'Object n'était pas si compliquée.

AnnanFay
la source
9
'hasOwnProperty' exclut les propriétés sur les prototypes de cet objet, ce qui est utile à connaître.
ijw
2
Réponse acceptée parce que c'est ainsi que j'ai fini par l'implémenter, mais je pense que cela aurait dû être une fonction intégrée du langage.
Pat
5
Notez que vous devez utiliser "for (var i in this) ..." pour éviter de créer une variable globale.
Brad G.13
5
J'éviterais de modifier Object.prototype - comme un autre commentateur l'a noté ci-dessous, cela peut facilement casser les scripts qui ne font pas attention à vérifier hasOwnProperty (). Au lieu de cela, utilisez la méthode la moins conviviale OO: définissez une fonction «touches» si elle n'existe pas déjà. (Firefox et Chrome implémentent tous deux une fonction native keys () qui fait exactement ce que l'OP veut - IE ne le fait pas)
digitalbath
1
Cela semble être une mauvaise idée d'ajouter quoi que ce soit à Object.prototype, car cela rompt chaque boucle normale comme: for (var k in array) {} ou for (var k in object), et cet idiome - bien qu'il puisse être erroné - est extrêmement commun. Par exemple, selon la réponse de Matthew Darwin ci-dessous, cela casse Google Maps.
Sam Watkins
42

vous pouvez utiliser Object.keys

Object.keys(h)
Leticia Santos
la source
3
Ajouté dans ECMAScript 5 mais devrait fonctionner dans la plupart des principaux navigateurs maintenant
Pat
33

Vous pouvez utiliser Underscore.js , qui est une bibliothèque utilitaire Javascript.

_.keys({one : 1, two : 2, three : 3}); 
// => ["one", "two", "three"]
Timotti
la source
Eh bien, ce n'est pas vraiment ce qui a été demandé, car @Pat cherche une fonction intégrée, mais c'est quand même une bibliothèque intéressante, et elle ne change pasObject.prototype
fresskoma
2
Ces jours-ci, je pense qu'il est beaucoup plus utile d'utiliser ces petites bibliothèques astucieuses que de continuer à écrire vos propres implémentations ... Quoi qu'il en soit, dans la plupart des projets du monde réel, nous utilisons de toute façon Underscore ou des bibliothèques équivalentes. Personnellement, je préfère utiliser Underscore.
kumarharsh
_.keys(obj).lengthpour voir s'il y a des clés.
chovy
13

C'est le mieux que vous puissiez faire, pour autant que je sache ...

var keys = [];
for (var k in h)keys.push(k);
danb
la source
2
Cela ne fonctionne pas non plus lorsque Object.prototype a été dérangé.
Phil
4
Il serait préférable de l'utiliser, et de ne pas "jouer avec" Object.prototype. Il semble que tout se brise si nous ajoutons des choses à Object.prototype: c'est un idiome extrêmement courant de boucler sur les clés d'un tableau / objet.
Sam Watkins
8

en utilisant jQuery, vous pouvez obtenir les clés comme ceci:

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

Ou:

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

merci à @pimlottc

chim
la source
3
Si vous vouliez emprunter cette voie, vous pourriez aussi bien utiliser JQuery.map: $.map(h, function(v,k) { return k; });
pimlottc
6

Je pense que vous pouvez parcourir les propriétés de l'objet en utilisant for / in, vous pouvez donc faire quelque chose comme ceci:

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

Je voulais utiliser la réponse la mieux notée ci-dessus

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

Cependant, lors de l'utilisation en conjonction avec l'API google maps v3, google maps n'est pas fonctionnel.

for (var key in h) ...

fonctionne bien.

Matthew Darwin
la source
1

si vous essayez d'obtenir uniquement les éléments mais pas les fonctions, ce code peut vous aider

this.getKeys = function() {

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

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

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

}

cela fait partie de mon implémentation du HashMap et je ne veux que les clés, thisest l'objet hashmap qui contient les clés

zeacuss
la source