javascript - node - ¿Por qué usar Object.prototype.hasOwnProperty.call(myObj, prop) en lugar de myObj.hasOwnProperty(prop)?
hasownproperty typescript (4)
Si entiendo correctamente, todos y cada uno de los objetos en Javascript heredan del prototipo de Objeto, lo que significa que todos y cada uno de los objetos en Javascript tienen acceso a la función hasOwnProperty a través de su cadena de prototipos.
Mientras leía el código fuente de require.js, me topé con esta función:
function hasProp(obj, prop) {
return hasOwn.call(obj, prop);
}
hasOwn
es una referencia a Object.prototype.hasOwnProperty
. ¿Hay alguna diferencia práctica para escribir esta función como
function hasProp(obj, prop) {
return obj.hasOwnProperty(prop);
}
Y ya que estamos en eso, ¿por qué definimos esta función? ¿Es solo una cuestión de accesos directos y almacenamiento en caché local del acceso a la propiedad para (leves) mejoras en el rendimiento, o me estoy perdiendo algún caso en el que se pueda usar hasOwnProperty en objetos que no tienen este método?
¿Hay alguna diferencia práctica [entre mis ejemplos]?
El usuario puede tener un objeto JavaScript creado con Object.create(null)
, que tendrá una cadena null
[[Prototype]]
, y por lo tanto no tendrá hasOwnProperty()
disponible en él. El uso de su segundo formulario no funcionará por este motivo.
También es una referencia más segura a Object.prototype.hasOwnProperty()
(y también más corto).
Puedes imaginar que alguien pudo haber hecho ...
var someObject = {
hasOwnProperty: function(lol) {
return true;
}
};
Lo que haría hasProp(someObject)
un hasProp(someObject)
si se hubiera implementado como su segundo ejemplo (encontraría ese método directamente en el objeto e invocaría eso, en lugar de ser delegado a Object.prototype.hasOwnProperty
).
Pero es menos probable que alguien haya anulado la referencia Object.prototype.hasOwnProperty
.
Y ya que estamos en eso, ¿por qué definimos esta función?
Véase más arriba.
¿Es solo una cuestión de accesos directos y almacenamiento local en caché del acceso a la propiedad para (leves) ganancias de rendimiento ...
Puede que sea más rápido en teoría, ya que no es necesario seguir la cadena [[Prototype]]
, pero sospecho que esto es insignificante y no la razón por la que la implementación es la razón.
... o me estoy perdiendo algún caso en el que
hasOwnProperty
pueda usarse en objetos que no tienen este método?
hasOwnProperty()
existe en Object.prototype
, pero se puede anular. Cada objeto nativo de JavaScript (pero no se garantiza que los objetos del host sigan esto, consulte la explicación detallada de Object.prototype
) tiene Object.prototype
como su último objeto en la cadena antes del null
(excepto, por supuesto, para el objeto devuelto por Object.create(null)
).
JavaScript no protege el nombre de la propiedad hasOwnProperty
Si existe la posibilidad de que un objeto tenga una propiedad con este nombre, es necesario usar una propiedad de propiedad de propiedad externa para obtener los resultados correctos:
Puede copiar y pegar los siguientes fragmentos de código en la consola de su navegador para comprender mejor
var foo = {
hasOwnProperty: function() {
return false;
},
bar: ''I belong to foo''
};
Siempre devuelve falso
foo.hasOwnProperty(''bar''); // false
Use la propiedad hasOwnProperty de otro Objeto y llámelo con este conjunto para foo
({}).hasOwnProperty.call(foo, ''bar''); // true
También es posible utilizar la propiedad hasOwnProperty del objeto prototipo para este propósito
Object.prototype.hasOwnProperty.call(foo, ''bar''); // true
Si entiendo correctamente, todos y cada uno de los objetos en Javascript heredan del prototipo de Objeto.
Puede parecer una división de pelos, pero existe una diferencia entre javascript (el término genérico para implementaciones de ECMAScript) y ECMAScript (el lenguaje utilizado para las implementaciones de javascript). Es ECMAScript el que define un esquema de herencia, no javascript, por lo que solo los objetos nativos de ECMAScript necesitan implementar ese esquema de herencia.
Un programa javascript en ejecución consta de al menos los objetos ECMAScript incorporados (Objeto, Función, Número, etc.) y probablemente algunos objetos nativos (por ejemplo, funciones). También puede tener algunos objetos host (como objetos DOM en un navegador u otros objetos en otros entornos host).
Mientras que los objetos incorporados y nativos deben implementar el esquema de herencia definido en ECMA-262, los objetos de host no lo hacen. Por lo tanto, no todos los objetos en un entorno javascript deben heredar de Object.prototype . Por ejemplo, los objetos host en IE implementados como objetos ActiveX arrojarán errores si se tratan como objetos nativos (por lo tanto, se usa try..catch para inicializar los objetos MS XMLHttpRequest). Algunos objetos DOM (como NodeLists en IE en modo peculiar) si se pasan a los métodos de Arreglo arrojarán errores, los objetos DOM en IE 8 y versiones inferiores no tienen un esquema de herencia similar a ECMAScript, y así sucesivamente.
Por lo tanto, no se debe suponer que todos los objetos en un entorno javascript heredan de Object.prototype.
lo que significa que todos y cada uno de los objetos en Javascript tienen acceso a la función hasOwnProperty a través de su cadena de prototipos
Lo que no es cierto para ciertos objetos de host en IE en modo peculiar (y IE 8 e inferior siempre) al menos.
Dado lo anterior, vale la pena reflexionar sobre por qué un objeto puede tener su propio método hasOwnProperty y la conveniencia de llamar a otro método hasOwnProperty sin probar primero si es una buena idea o no.
Editar
Sospecho que la razón para usar Object.prototype.hasOwnProperty.call
es que en algunos navegadores, los objetos del host no tienen un método hasOwnProperty , usando call y el método incorporado es una alternativa. Sin embargo, hacerlo de forma genérica no parece una buena idea por las razones mencionadas anteriormente.
En lo que respecta a los objetos del host, el operador in puede usarse para probar propiedades en general, por ejemplo,
var o = document.getElementsByTagName(''foo'');
// false in most browsers, throws an error in IE 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'');
Una alternativa (probado en IE6 y otros):
function ownProp(o, prop) {
if (''hasOwnProperty'' in o) {
return o.hasOwnProperty(prop);
} else {
return Object.prototype.hasOwnProperty.call(o, prop);
}
}
De esa manera, solo llama específicamente a la propiedad hasOwn incorporada donde el objeto no la tiene (heredada o de otro tipo).
Sin embargo, si un objeto no tiene un método hasOwnProperty
, es probable que sea tan adecuado para usar el operador in , ya que el objeto probablemente no tiene un esquema de herencia y todas las propiedades están en el objeto (eso es solo una suposición), por ejemplo El operador in es una forma común (y aparentemente exitosa) de probar el soporte de objetos DOM para propiedades.
La información dada en ambas respuestas existentes es acertada. Sin embargo, el uso de:
(''propertyName'' in obj)
se menciona un par de veces. Se debe tener en cuenta que las implementaciones de hasOwnProperty
devolverán verdadero solo si la propiedad está contenida directamente en el objeto que se está probando.
El operador interno inspeccionará hacia abajo a través de la cadena del prototipo también.
Esto significa que las propiedades de la instancia devolverán verdadero cuando se pasa a hasOwnProperty
donde las propiedades del prototipo devolverán falso.
Usando el operador in
, tanto las propiedades de instancia como de prototipo devolverán verdadero.