141 votes

Pourquoi utiliser Object.prototype.hasOwnProperty.call(myObj, prop) au lieu de myObj.hasOwnProperty(prop) ?

Si je comprends bien, chaque objet en JavaScript hérite du prototype Object, ce qui signifie que chaque objet en JavaScript a accès à la fonction hasOwnProperty via sa chaîne de prototypes.

En lisant RequireJS Je suis tombé sur cette fonction :

function hasProp(obj, prop) {
    return hasOwn.call(obj, prop);
}

hasOwn est une référence à Object.prototype.hasOwnProperty . Y a-t-il une différence pratique à écrire cette fonction sous forme de

function hasProp(obj, prop) {
    return obj.hasOwnProperty(prop);
}

Et puisque nous y sommes, pourquoi définir cette fonction ? S'agit-il seulement d'une question de raccourcis et de mise en cache locale de l'accès aux propriétés pour un (léger) gain de performance, ou est-ce que je rate des cas où hasOwnProperty pourrait être utilisé sur des objets qui n'ont pas cette méthode ?

138voto

alex Points 186293

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 un null [[Prototype]] de la chaîne, et n'aura donc pas hasOwnProperty() disponible sur celui-ci. L'utilisation de votre deuxième formulaire ne fonctionnerait pas pour cette raison.

C'est aussi une référence plus sûre pour Object.prototype.hasOwnProperty() (et aussi plus court).

Vous pouvez imaginer que quelqu'un a pu faire...

var someObject = {
    hasOwnProperty: function(lol) {
        return true;
    }
};

Ce qui ferait un hasProp(someObject) si elle avait été implémentée comme dans votre deuxième exemple (elle aurait trouvé cette méthode directement sur l'objet et l'aurait invoquée, au lieu d'être déléguée à l'utilisateur). Object.prototype.hasOwnProperty ).

Mais il est moins probable que quelqu'un ait pris le dessus sur l'option Object.prototype.hasOwnProperty référence.

Et puisque nous y sommes, pourquoi définir cette fonction ?

Voir ci-dessus.

Est-ce que c'est juste une question de raccourcis et de mise en cache locale de l'accès aux propriétés pour (légers) gains de performance...

Cela peut rendre plus rapide en théorie, comme le [[Prototype]] Il n'est pas nécessaire de suivre la chaîne, mais je pense que c'est négligeable et no la raison pour laquelle la mise en œuvre est ce qu'elle est.

... ou est-ce que je rate des cas où hasOwnProperty pourrait être utilisée sur des objets qui ne possèdent pas cette méthode ?

hasOwnProperty() existe sur Object.prototype mais elle peut être remplacée. Chaque objet JavaScript natif (mais il n'est pas garanti que les objets hôtes suivent cette règle), voir l'explication approfondie de RobG ) a Object.prototype comme dernier objet de la chaîne avant null (sauf bien sûr pour l'objet retourné par Object.create(null) ).

18voto

RobG Points 41170

Si j'ai bien compris, chaque objet en JavaScript hérite du prototype Object.

On pourrait croire qu'il s'agit de couper les cheveux en quatre, 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 l'ECMAScript qui définit un schéma d'héritage, et non le JavaScript, de sorte que seuls les objets ECMAScript natifs doivent mettre en œuvre ce schéma d'héritage.

Un programme JavaScript en cours d'exécution est constitué d'au moins les objets ECMAScript intégrés (Objet, Fonction, Nombre, etc.) et probablement de quelques objets natifs (par exemple, des fonctions). Il peut également contenir 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 mettre en œuvre le schéma d'héritage défini dans la norme ECMA-262, les objets hôtes ne le font pas. Par conséquent, les objets d'un environnement JavaScript ne sont pas tous doit hériter de Objet.prototype . Par exemple, dans Internet Explorer, les objets hôtes sont implémentés en tant que ActiveX entraîneront des erreurs s'ils sont traités comme des objets natifs (d'où la raison pour laquelle les essayer..attraper est utilisé pour initialiser Microsoft XMLHttpRequest ). Certains objets DOM (comme les NodeLists dans Internet Explorer en mode quirks), s'ils sont passés aux méthodes Array, provoqueront des erreurs, les objets DOM dans Internet Explorer 8 et inférieur n'ont pas un schéma d'héritage de type ECMAScript, et ainsi de suite.

Il ne faut donc pas supposer que tous les objets d'un environnement JavaScript héritent de Object.prototype.

ce qui signifie que chaque objet en JavaScript a accès à la fonction hasOwnProperty par le biais de sa chaîne de prototypes.

Ce qui n'est pas vrai pour certains objets hôtes dans Internet Explorer en mode quirks (et Internet Explorer 8 et inférieur toujours) au moins.

Compte tenu de ce qui précède, il convient de se demander pourquoi un objet peut avoir son propre hasOwnProperty et l'opportunité d'appeler une autre méthode hasOwnProperty sans avoir testé au préalable si c'était une bonne idée ou non.

Je soupçonne que la raison de l'utilisation de Object.prototype.hasOwnProperty.call est que dans certains navigateurs, les objets hôtes n'ont pas d'icône hasOwnProperty en utilisant appelez 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, le sur L'opérateur peut être utilisé pour tester les propriétés de manière générale, par ex.

var o = document.getElementsByTagName('foo');

// false in most browsers, throws an error in Internet Explorer 6, and probably 7 and 8
o.hasOwnProperty('bar');

// false in all browsers
('bar' in o);

// false (in all browsers? Do some throw errors?)
Object.prototype.hasOwnProperty.call(o, 'bar');

Une alternative (testée dans Internet Explorer 6 et autres) :

function ownProp(o, prop) {

  if ('hasOwnProperty' in o) {
    return o.hasOwnProperty(prop);

  } else {
    return Object.prototype.hasOwnProperty.call(o, prop);
  }
}

De cette façon, vous n'appelez spécifiquement que la fonction intégrée hasOwnProperty lorsque l'objet ne l'a pas (hérité ou non).

Cependant, si un objet n'a pas d'objet de type hasOwnProperty il est probablement tout aussi approprié d'utiliser la méthode sur 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 qu'une supposition), par exemple l'opérateur sur est une façon courante (et apparemment réussie) de tester le support des propriétés par les objets DOM.

14voto

Sudharshan Points 19

JavaScript ne protège pas le nom de la propriété hasOwnProperty

S'il est possible qu'un objet ait une propriété portant 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.

var foo = {
  hasOwnProperty: function() {
    return false;
  },
  bar: 'I belong to foo'
};

Renvoie toujours false

foo.hasOwnProperty('bar'); // false

Utiliser la propriété hasOwnProperty d'un autre objet et l'appeler avec ce réglé sur foo

({}).hasOwnProperty.call(foo, 'bar'); // true

Il est également possible d'utiliser la propriété hasOwnProperty de l'objet Objet prototype à cette fin

Object.prototype.hasOwnProperty.call(foo, 'bar'); // true

3voto

steve Points 1

Les informations données dans les deux premières réponses (par date) sont exactes. Cependant, l'utilisation de :

('propertyName' in obj)

est mentionné à plusieurs reprises. Il convient de noter que le hasOwnProperty retournera vrai seulement si la propriété est directement contenue dans l'objet testé.

Le site in L'opérateur inspectera également la chaîne des prototypes.

Cela signifie que les propriétés d'instance renverront la réponse vraie lorsqu'elles seront passées à la fonction hasOwnProperty alors que les propriétés du prototype retourneront false.

Utilisation de la in l'opérateur, les propriétés d'instance et de prototype renverront toutes deux à true.

3voto

Ran Turner Points 1648

En plus du reste des réponses ici, notez que vous pouvez utiliser la nouvelle méthode Object.hasOwn (supporté par la plupart des navigateurs et bientôt par les autres) au lieu de Object.hasOwnProperty.call car il vous permet d'écrire un code plus court et plus rapide.

En savoir plus Object.hasOwn - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn

Compatibilité des navigateurs - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn#browser_compatibility

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X