2010-09-08 3 views
1

J'ai besoin de quelque chose d'un HashMap en javascript. Pouvons-nous faire ceci:En utilisant un objet javascript comme une carte java?

var map = {}; 
map['foo'] = true; 
map['zoo'] = true; 
... 

if (map['foo']) { 
    // yes, foo exists. 
} 
else { 
    // no, foo does not exist. 
} 

Comment vérifier correctement l'existence de la propriété sans l'insérer si elle n'existe pas? Par exemple, je ne veux map.foo exister après la vérification ci-dessus si je ne pas ajouter explicitement,

Merci

Répondre

9

Dans votre exemple, pour vérifier:

if (map['foo']) { 
    //.. 
} 

Non vérifie uniquement si la propriété n'est pas définie sur l'objet, l'expression de condition de l'instruction if évalue à false également si la propriété contient une valeur qui se contraint à false sur le contexte booléen (alias valeurs falsifiées), par exemple 0, NaN, un chaîne vide, null, undefined et bien sûr false, par exemple:

var map = { 
    'foo': 0 // or any other falsy value 
}; 

if (map['foo']) { 
    // foo is truthy... 
} else { 
    // foo is falsy or not defined 
} 

Pour vérifier si une propriété existe sur un objet, quelle que soit sa valeur -qui peut être falsy, même undefined -, vous pouvez utiliser la méthode hasOwnProperty , par exemple:

var map = {}; 
map['foo'] = 0; 

if (map.hasOwnProperty('foo')) { 
    // foo exist physically on the object... 
} 

Le seul problème avec cette méthode est que si quelqu'un ajoute une propriété nommée hasOwnProperty à un objet, il ne fonctionnera pas, par exemple:

var obj = { 
    hasOwnProperty: 'bar' 
}; 

Si vous exécutez obj.hasOwnProperty('prop'), il vous donnera un TypeError, parce que l'objet contient une propriété de chaîne ombres la méthode -invoking la chaîne provoquerait la ERROR-.

Une solution à cela est d'appeler la méthode hasOwnProperty directement à partir de l'objet Object.prototype, par exemple:

if (Object.prototype.hasOwnProperty.call(obj, 'prop')) { 
    //.. 
} 

Vous pouvez également utiliser le in operator:

if ('prop' in obj) { 
    //... 
} 

La différence avec la première méthode est que l'opérateur in vérifie également les propriétés héritées, par exemple:

var obj = {}; 
obj.hasOwnProperty('toString'); // false 
'toString' in obj; // true, inherited from Object.prototype.toString 

Voir aussi:

Edit:

Extension ma réponse au commentaire de @slebetman, sur la vérification if (map.foo !== undefined).

Comme je commentais, il y a des préoccupations au sujet de l'accès à la propriété globale undefined et aussi une différence sémantique entre vérification d'une valeur de la propriété par rapport existence de la propriété.

La propriété globale undefined n'est pas défini en lecture seule ECMAScript 3e édition Standard, (est maintenant writable = false sur ES5 :)

Dans presque toutes les implémentations sa valeur peut être remplacée.

Si quelqu'un fait:

window.undefined = 'foo'; 

// It will break your code: 
var obj = {}; 
if (obj.foo !== undefined) { 
    alert("This shouldn't ever happen!"); 
} 

aussi la différence sémantique: en testant si map.foo !== undefined nous ne vérifient pas sur le plan technique que si la propriété existe sur l'objet ou non, une propriété peut exister, exploitation non définie comme valeur , par exemple:

var map = { 
    'foo': undefined 
}; 

map.hasOwnProperty('foo'); // true, because the property exists although 
          //  it holds the undefined value 
map.foo !== undefined;  // false 
+1

Pour les objets vides créés directement à partir de l'objet Object (ce qui est vrai dans ce cas), l'utilisation de hasOwnProperty n'est pas nécessaire. Vérifiez directement si la valeur n'est pas définie: 'if (map.foo! == undefined)'. – slebetman

+0

@slebetman, oui mais l'accès à la propriété globale 'undefined' en tant qu'identifiant ne pose aucun problème, 1. ne fait pas partie d'ECMAScript 3, (est maintenant défini sur ES5 :), 2. Dans certaines implémentations, la propriété n'est pas lue -seulement, sa valeur peut être remplacée, par exemple si quelqu'un fait 'window.undefined = true;', il va casser votre code. En vérifiant également 'map.foo! == undefined' nous ne vérifions pas techniquement si la propriété * existe * sur l'objet ou non, une propriété * peut * exister, en maintenant' undefined' comme valeur. – CMS

+0

@slebetman - Réfléchissez également aux modifications de 'Object.prototype'. Essayez ceci dans votre navigateur: 'javascript: Object.prototype.foo = 5; bar = {}; alert ((bar.foo! == undefined) +", "+ bar.hasOwnProperty (" foo ")); Object. prototype.hasOwnProperty = function() {return vrai}; alert (bar.hasOwnProperty ("baz")) ' –

0

En utilisant JavaScript Hashmap Equivalent

 
<html> 
<head> 
<script> 
HashMap = function(){ 
    this._dict = {}; 
} 
HashMap.prototype._shared = {id: 1}; 
HashMap.prototype.put = function put(key, value){ 
    if(typeof key == "object"){ 
    if(!key.hasOwnProperty._id){ 
     key.hasOwnProperty = function(key){ 
     return Object.prototype.hasOwnProperty.call(this, key); 
     } 
     key.hasOwnProperty._id = this._shared.id++; 
    } 
    this._dict[key.hasOwnProperty._id] = value; 
    }else{ 
    this._dict[key] = value; 
    } 
    return this; // for chaining 
} 
HashMap.prototype.get = function get(key){ 
    if(typeof key == "object"){ 
    return this._dict[key.hasOwnProperty._id]; 
    } 
    return this._dict[key]; 
} 


var color = {}; // unique object instance 
var shape = {}; // unique object instance 
var map = new HashMap(); 
map.put(color, "blue"); 
map.put(shape, "round"); 
console.log("Item is", map.get(color), "and", map.get(shape)); 
</script> 

<head> 
<body> 
<script>document.write("Existing Item Testing :\t\t\t" + map.get(color)+"
"); document.write("Non - Existing Item Testing :\t\t\t" + map.get("test")+ ""); </body> </html>

Sortie:

Existing Item Testing : blue 
Non - Existing Item Testing : undefined 
0

Java Carte et Java HashMap sont des choses différentes. Java Map est une table de hachage dotée de valeurs étiquetées par clé et d'une recherche rapide des valeurs par les clés. HashMap d'un autre côté a le même temps de fuite si vous recherchez une valeur par clé ou par clé.

J'ai écrit une structure de données similaire à Java Map, mais je suis encore en train de développer la classe HashMap pour javascript et je la partagerai dès que possible. Notez que ma solution est juste un wrapper à la table de hachage native, pour une utilisation et une itération plus faciles. Un peu plus lent mettre et supprimer des temps, et un peu plus de mémoire.

Vous pouvez le vérifier sur mon blog, car il est trop long pour ici: http://stamat.wordpress.com/javascript-map-class/

Merci pour lui donner une chance! Les commentaires sont très appréciés! :)

Questions connexes