Ambos, acceder a una propiedad que no está definida en un objeto y una propiedad que contiene el valor primitivo undefined
, le devolverá undefined
.
Por ejemplo:
var obj = {
a: undefined
};
obj.a; // undefined
obj.b; // undefined
La diferencia es que a
es una propiedad propia, y no es b
:
obj.hasOwnProperty('a'); // true
obj.hasOwnProperty('b'); // false
En el primer caso a
es una propiedad propia, incluso si contiene undefined
como su valor. En el segundo caso, b
no es una propiedad propia, al acceder al obj.b
buscará una propiedad denominada b
, en la cadena del prototipo.
Cuando finaliza la cadena del prototipo (cuando llega a un objeto con null
[[Prototype]]
), la búsqueda de propiedades finaliza y undefined
se devuelve explícitamente.
Usted debe saber que los hasOwnProperty
método comprueba si la propiedad existe físicamente en el objeto (propios propiedades), pero también tenemos heredaron propiedades, para ese caso podemos utilizar el in
operator, por ejemplo:
function Test() {}
Test.prototype.a = 'foo'; // instances of Test will inherit from Test.prototype
var obj = new Test(); // { a="foo", b="bar"}
obj.b = 'bar';
obj.hasOwnProperty('a'); // false
'a' in obj; // true
obj.a; // 'foo'
obj.hasOwnProperty('b'); // true
Como se puede ver, obj
hereda de Test.prototype
, y la propiedad a
no es una propiedad , pero está disponible a través de la cadena de prototipo. Es por eso que hasOwnProperty
devuelve false
y el operador in
devuelve true
.
Se puede ver cómo las propiedades internamente se resuelven por la operación [[Get]]
interna
Notas:
- Acceso
undefined
como un identificador no se considera para estar seguro en ECMAScript 3 (el más ampliamente implementado versión del estándar de idioma), porque en lugar de ser una palabra clave de idioma (como null
por ejemplo) es solo una propiedad del objeto global, y se puede escribir en esta versión de la especificación, lo que significa que si alguien reemplaza su val ue (p. window.undefined = 'LOL';
), romperá su código.
El typeof
operator como @strager menciones puede utilizarse en lugar, por ejemplo:
if (typeof obj.prop == 'undefined') { /*....*/ }
Este operador devuelve siempre una cadena (que es seguro de usar ==
:), y su valor depende del tipo de su operando, los valores posibles se describen here.
Otra forma común de resolver esto es para declarar su propio undefined
variables, disponible en el ámbito de sus funciones, por ejemplo, algunas bibliotecas utilizan el siguiente patrón:
(function(undefined) {
// code here
})();
La función tiene un argumento con nombre undefined
, y se ejecuta inmediatamente sin pasarle ningún valor (el último par o parens realiza la invocación).
Quizás vale la pena mencionar que el undefined
global property finalmente se describió en ECMAScript 5 como no grabable (inmutable, así como no enumerable y no configurable -no eliminable-).
Utilizando el método hasOwnProperty
directamente de una instancia de objeto también no se considera como seguro, porque si algo de objeto tiene una propiedad con el mismo nombre, será ensombrecido el método inicial. Por ejemplo:
var obj = { hasOwnProperty: function() { /* evil code :) */ } };
Si llama:
obj.hasOwnProperty('prop');
se ejecutará el método definido en el objeto (y que no le gustaría esto, ya que sabe exactamente qué método desea invocar ...), porque sombras la una de la Object.prototype
, sin embargo, puede ser invocado de forma segura por:
Object.prototype.hasOwnProperty.call(obj, 'prop');
Además de '.hasOwnProperty', también está el operador' in' que, creo, necesita mencionarse. – strager
@strager: Sí ... estoy en ello ... – CMS
En su primera nota: especifique que, para verificar si un valor no está definido, use 'typeof x === 'undefined''. Además, no veo por qué 'Object.prototype.hasOwnProperty' se consideraría inseguro; Lo uso para el mismo propósito por el cual afirma que no es seguro. ¿Puedes aclarar sobre este punto? – strager