Y a-t-il une différence pratique [entre mes exemples]?
L'utilisateur peut avoir un objet JavaScript créé avec Object.create(null)
, qui aura une null
[[Prototype]]
chaîne, et donc ne sera pas hasOwnProperty()
disponible dessus. L'utilisation de votre deuxième formulaire échouerait pour cette raison.
C'est aussi une référence plus sûre Object.prototype.hasOwnProperty()
(et aussi plus courte).
Vous pouvez imaginer que quelqu'un a pu faire ...
var someObject = {
hasOwnProperty: function(lol) {
return true;
}
};
Ce qui ferait un hasProp(someObject)
échec s'il avait été implémenté comme votre deuxième exemple (il trouverait cette méthode directement sur l'objet et l'invoquerait, au lieu d'être délégué à Object.prototype.hasOwnProperty
).
Mais il est moins probable que quelqu'un ait remplacé la Object.prototype.hasOwnProperty
référence.
Et puisque nous y sommes, pourquoi définissons-nous cette fonction?
Voir au dessus.
Est-ce juste une question de raccourcis et de mise en cache locale de l'accès aux propriétés pour de (légers) gains de performances ...
Cela peut le rendre plus rapide en théorie, car la [[Prototype]]
chaîne n'a pas à être suivie, mais je soupçonne que cela est négligeable et non la raison pour laquelle la mise en œuvre est la raison pour laquelle elle l'est.
... ou est-ce que je manque des cas où
hasOwnProperty
pourraient être utilisés sur des objets qui n'ont pas cette méthode?
hasOwnProperty()
existe Object.prototype
, mais peut être remplacé. Chaque objet JavaScript natif (mais les objets hôtes ne sont pas garantis de suivre cela, voir l'explication détaillée de RobG ) a Object.prototype
comme dernier objet sur la chaîne avant null
(sauf bien sûr pour l'objet renvoyé par Object.create(null)
).
const hasProp = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop)
Cela peut sembler couper les cheveux, mais il y a une différence entre javascript (le terme générique pour les implémentations ECMAScript) et ECMAScript (le langage utilisé pour les implémentations javascript). C'est ECMAScript qui définit un schéma d'héritage, et non javascript, donc seuls les objets ECMAScript natifs doivent implémenter ce schéma d'héritage.
Un programme javascript en cours d'exécution comprend au moins les objets ECMAScript intégrés (objet, fonction, nombre, etc.) et probablement certains objets natifs (par exemple des fonctions). Il peut également avoir des objets hôtes (tels que des objets DOM dans un navigateur ou d'autres objets dans d'autres environnements hôtes).
Alors que les objets intégrés et natifs doivent implémenter le schéma d'héritage défini dans ECMA-262, les objets hôtes ne le font pas. Par conséquent, tous les objets d'un environnement javascript ne doivent pas hériter d' Object.prototype . Par exemple, les objets hôte dans IE implémentés en tant qu'objets ActiveX généreront des erreurs s'ils sont traités comme des objets natifs (d'où la raison pour laquelle try..catch est utilisé pour initialiser les objets MS XMLHttpRequest). Certains objets DOM (comme NodeLists dans IE en mode quirks), s'ils sont passés aux méthodes Array, génèrent des erreurs, les objets DOM dans IE 8 et les versions antérieures n'ont pas de schéma d'héritage de type ECMAScript, etc.
Par conséquent, il ne faut pas supposer que tous les objets dans un environnement javascript héritent d'Object.prototype.
Ce qui n'est pas vrai pour certains objets hôtes dans IE en mode quirks (et IE 8 et inférieur toujours) au moins.
Compte tenu de ce qui précède, il vaut la peine de se demander pourquoi un objet peut avoir sa propre méthode hasOwnProperty et l'opportunité d'appeler une autre méthode hasOwnProperty à la place sans tester au préalable si c'est une bonne idée ou non.
Éditer
Je soupçonne que la raison de l'utilisation
Object.prototype.hasOwnProperty.call
est que dans certains navigateurs, les objets hôtes n'ont pas de méthode hasOwnProperty , l'utilisation de call et la méthode intégrée est une alternative. Cependant, le faire de manière générique ne semble pas être une bonne idée pour les raisons mentionnées ci-dessus.En ce qui concerne les objets hôtes, l' opérateur in peut être utilisé pour tester les propriétés en général, par exemple
Une alternative (testée dans IE6 et autres):
De cette façon, vous n'appelez spécifiquement le hasOwnProperty intégré que là où l'objet ne l'a pas (hérité ou autre).
Cependant, si un objet n'a pas de
hasOwnProperty
méthode, il est probablement tout aussi approprié d'utiliser l' opérateur in car l'objet n'a probablement pas de schéma d'héritage et toutes les propriétés sont sur l'objet (ce n'est cependant qu'une hypothèse), par exemple le in est une manière courante (et apparemment réussie) de tester la prise en charge des objets DOM pour les propriétés.la source
in
n'effectue pas dehasOwnProperty()
recherche, je soupçonne que la propriété que vous recherchiez existait sur la chaîne de prototypes.hasOwnProperty
directement l'objet résultant, car un client malveillant pourrait envoyer une valeur JSON comme{"hasOwnProperty": 1}
et provoquer le plantage du serveur.S'il est possible qu'un objet ait une propriété avec ce nom, il est nécessaire d'utiliser un hasOwnProperty externe pour obtenir des résultats corrects:
Vous pouvez copier-coller les extraits de code ci-dessous dans la console de votre navigateur pour mieux comprendre
Renvoie toujours false
Utilisez hasOwnProperty d'un autre objet et appelez-le avec cet ensemble à foo
Il est également possible d'utiliser la propriété hasOwnProperty du prototype Object à cette fin
la source
hasOwnProperty
retourstrue
.Les informations données dans les deux réponses existantes sont parfaites. Cependant, l'utilisation de:
est mentionné à quelques reprises. Il est à noter que les
hasOwnProperty
implémentations ne renverront true que si la propriété est directement contenue sur l'objet testé.L'
in
opérateur inspectera également la chaîne du prototype.Cela signifie que les propriétés de l'instance renverront true lorsqu'elles seront transmises à
hasOwnProperty
où les propriétés du prototype renverront false.En utilisant l'
in
opérateur, les propriétés d'instance et de prototype renverront true.la source