Les deux instructions suivantes produisent-elles le même résultat? Y a-t-il une raison de préférer une voie à l'autre?
if (key in object)
if (object.hasOwnProperty(key))
Les deux instructions suivantes produisent-elles le même résultat? Y a-t-il une raison de préférer une voie à l'autre?
if (key in object)
if (object.hasOwnProperty(key))
Réponses:
Attention, ils ne produiront pas le même résultat.
inretournera également truesi keyobtient trouvé quelque part dans la chaîne de prototypes , alors que Object.hasOwnProperty(comme le nom nous l'indique déjà), ne retournera que truesi keyest disponible sur cet objet directement (sa "possède" la propriété).
({foo:"bar"}).hasOwnProperty("toString")vs"toString" in ({foo:"bar"})
J'essaierai d'expliquer avec un autre exemple. Disons que nous avons l'objet suivant avec deux propriétés:
function TestObj(){
this.name = 'Dragon';
}
TestObj.prototype.gender = 'male';
Créons une instance de TestObj:
var o = new TestObj();
Examinons l'instance d'objet:
console.log(o.hasOwnProperty('name')); // true
console.log('name' in o); // true
console.log(o.hasOwnProperty('gender')); // false
console.log('gender' in o); // true
Conclusion:
in operator retourne toujours vrai, si la propriété est accessible par l'objet, directement ou depuis le prototype
hasOwnProperty () renvoie true uniquement si la propriété existe sur l'instance, mais pas sur son prototype
Si nous voulons vérifier qu'une propriété existe sur le prototype, logiquement, nous dirons:
console.log(('name' in o) && !o.hasOwnProperty('name')); //false
console.log(('gender' in o) && !o.hasOwnProperty('gender')); //true - it's in prototype
Finalement:
Donc, en ce qui concerne l'affirmation que ces deux conditions ...
if (key in object)
if (object.hasOwnProperty(key))
... produire le même résultat, la réponse est évidente, cela dépend.
invérifiera également les propriétés héritées, ce qui n'est pas le cas hasOwnProperty.
En résumé, hasOwnProperty()ne regarde pas dans le prototype alors inque regarde dans le prototype.
Tiré de O'Reilly High Performance Javascript :
Vous pouvez déterminer si un objet a un membre d'instance avec un nom donné à l'aide de la méthode hasOwnProperty () et en passant le nom du membre. Pour déterminer si un objet a accès à une propriété avec un nom donné, vous pouvez utiliser l'opérateur in. Par exemple:
var book = {
title: "High Performance JavaScript",
publisher: "Yahoo! Press"
};
alert(book.hasOwnProperty("title")); //true
alert(book.hasOwnProperty("toString")); //false
alert("title" in book); //true
alert("toString" in book); //true
Dans ce code, hasOwnProperty () renvoie true lorsque «title» est passé car title est une instance d'objet; la méthode renvoie false lorsque «toString» est passé car il n'existe pas sur l'instance. Lorsque chaque nom de propriété est utilisé avec l'opérateur in, le résultat est vrai les deux fois car il recherche l'instance et le prototype.
Vous avez de très bonnes réponses. Je veux juste offrir quelque chose qui vous évitera d'avoir à vérifier "hasOwnProperty" lors de l'itération d'un objet.
Lors de la création d'un objet, les gens le créeront généralement de cette manière:
const someMap = {}
// equivalent to: Object.create(Object.prototype)
// someMap.constructor will yield -> function Object() { [native code] }
Maintenant, si vous voulez parcourir "someMap", vous devrez le faire de cette façon:
const key
for(key in someMap ){
if (someMap.hasOwnProperty(key)) {
// Do something
}
}
Nous le faisons afin d'éviter d'itérer sur des propriétés héritées.
Si vous avez l'intention de créer un objet simple qui ne sera utilisé que comme une "carte" (c'est-à-dire des paires clé-valeur), vous pouvez le faire comme ça:
const newMap = Object.create(null);
// Now, newMap won't have prototype at all.
// newMap.constructor will yield -> undefined
Alors maintenant, il sera prudent d'itérer comme ceci:
for(key in cleanMap){
console.log(key + " -> " + newMap [key]);
// No need to add extra checks, as the object will always be clean
}
J'ai appris cette astuce géniale ici
L'autre formulaire (appelé dans) énumère les noms de propriété (ou clés) d'un objet. À chaque itération, une autre chaîne de nom de propriété de l'objet est affectée à la variable. Il est généralement nécessaire de tester object.hasOwnProperty (variable) pour déterminer si le nom de propriété est vraiment un membre de l'objet ou a été trouvé à la place sur la chaîne de prototypes.
for (myvar in obj) {
if (obj.hasOwnProperty(myvar)) { ... } }
(extrait du Javascript de Crockford : The Good Parts )
inopérateur est différent de l' for-ininstruction.
inc'est un mot-clé. Mais OP pose des questions sur l'utilisation spécifique en tant inqu'opérateur. Votre réponse traite de l'autre utilisation dans le cadre de la for-indéclaration.
La première version est plus courte (notamment en code minifié où les variables sont renommées)
a in b
contre
b.hasOwnProperty(a)
Quoi qu'il en soit, comme le disait @AndreMeinhold, ils ne produisent pas toujours le même résultat.
in will also return true if key gets found somewhere in the prototype chain. pouvez-vous écrire un exemple? Merci.