2010-08-05 12 views
22

Consulte http://jsfiddle.net/FDhQF/1/ para obtener un ejemplo trivial.Diferencia entre indefinido y no definido en Javascript

¿Cuál es la diferencia entre algo indefinido y algo no definido en Javascript? Por ejemplo, tratar de acceder a una propiedad para un objeto (efectivamente, tratando de acceder a una variable) que no está definido devolverá undefined. Pero también puede establecer algo = undefined. Cuando lo haces, intentar acceder a él sigue siendo indefinido, pero el puntero aún está allí. Un ejemplo, como el anterior, es cómo iterar sobre un objeto aún pasa por encima de la propiedad que usted ha (re) declarado como indefinido. Parece que hay dos tipos diferentes de indefinidos. ¿Alguien puede arrojar algo de luz sobre la situación?

Respuesta

39

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'); 
+0

Además de '.hasOwnProperty', también está el operador' in' que, creo, necesita mencionarse. – strager

+0

@strager: Sí ... estoy en ello ... – CMS

+1

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

1

Here es una buena explicación de "indefinido". Sin embargo, la esencia es que establecer algo para "indefinido" no es definido por la ONU, porque "indefinido" es en realidad un valor primitivo, que se utiliza cuando una variable (o propiedad) no tiene asignado un valor.

+0

'undefined' es en realidad una variable establecida inicialmente en el valor primitivo. El valor primitivo se usa, no la variable, al regresar de una función sin un valor de retorno explícito, por ejemplo. – strager

+1

Además, el enlace que proporcionó no parece responder la pregunta directamente. – strager

Cuestiones relacionadas