2009-04-22 38 views
65

NOTA: según ECMAScript5.1, section 15.1.1.3, window.undefined es de solo lectura.JavaScript: undefined! == undefined?

  • navegadores modernos implementan esto correctamente. por ejemplo: Safari 5.1, Firefox 7, Chrome 20, etc.
  • Indefinido sigue siendo modificable en: Chrome 14, ...

Cuando recientemente integré Facebook Connect con Tersus, que inicialmente recibieron el los mensajes de error Invalid Enumeration Value y Handler already exists al intentar llamar a las funciones de la API de Facebook.

Resultó que la causa del problema era

object.x === undefined 

regresando falso cuando no hay ninguna propiedad 'x' en 'objeto'.

trabajé en torno al problema mediante la sustitución de igualdad estricta con la igualdad regular en dos funciones de Facebook:

FB.Sys.isUndefined = function(o) { return o == undefined;}; 
FB.Sys.containsKey = function(d, key) { return d[key] != undefined;}; 

Esto hizo que las cosas funcionan para mí, pero parece hacer alusión a algún tipo de colisión entre código y JavaScript de Facebook de mi propio.

¿Qué podría causar esto?

Sugerencia: Está bien documentado que undefined == null mientras que undefined !== null. Este no es el problema aquí. La pregunta es cómo se obtiene undefined !== undefined.

+5

Interesante, acabo de intentar en mi consola. 'var a = {}; a.b === undefined // true'. ¿Estás seguro de que tu 'object.x === undefined' devolviendo falso era porque no había un campo x en el objeto? –

+1

"Según ECMAScript5.1, sección 15.1.1.3, window.undefined es de solo lectura."- Horray, porque en la versión anterior, alguien podía sobrescribir' undefined' globalmente, y todo se rompería :( – Dan

Respuesta

59

Resulta que se puede establecer window.undefined a lo que usted quiere, y así obtener object.x !== undefined cuando object.x es la verdadera indefinido. En mi caso, inadvertidamente establecí indefinido a nulo.

La forma más fácil de ver que esto suceda es:

window.undefined = null; 
alert(window.xyzw === undefined); // shows false 

Por supuesto, esto no es probable que suceda. En mi caso, el error fue un poco más sutil, y fue equivalente a la siguiente situación.

var n = window.someName; // someName expected to be set but is actually undefined 
window[n]=null; // I thought I was clearing the old value but was actually changing window.undefined to null 
alert(window.xyzw === undefined); // shows false 
+16

¡Ah, ja! Y * este * es la razón principal por la que estoy en contra de usar la propiedad indefinida (en lugar de usar typeof). Felicidades por trabajar con el error. +1 – annakata

+2

Otra razón para usar siempre el espacio de nombres de tus objetos ... var n = blah.someName; blah [n] = null; le hubiera impedido obtener ese error ... – cmcculloh

+0

No se pudo sobrescribir en los navegadores modernos aunque – Memke

88

El problema es que undefined en comparación con null con == da como verdadero. Por tanto, el cheque común para indefinida se hace así:

typeof x == "undefined" 

Esto asegura que el tipo de la variable es muy indefinido.

+60

La mayor equivocación en muchas de las respuestas aquí es que 'undefined' es una palabra clave Javascript. No es una palabra clave, pero una variable que (la mayoría de las veces) pasa a ser indefinida. Por lo tanto, el único momento en que funciona "somevar === undefined" es cuando la variable "indefinida" realmente no se ha definido. He visto código (jcanvas) donde el La función de ajuste de clase incluye un último argumento llamado 'indefinido' (que nunca se usa) solo para asegurar que haya una variable indefinida llamada 'indefinida' dentro del alcance de la función. Además de situaciones especiales como esa, usar 'typeof' es el único "right" way. –

+1

¿Significa que en lugar de indefinido también podría usar Garglblarg mientras no se defina? –

+1

@ Dercsár: Sí, 'var foo; foo === undefined // true'. – pimvdb

2

A). Nunca he tenido y nunca confiaré en ninguna herramienta que pretenda producir código sin la codificación del usuario, que se duplica cuando es una herramienta gráfica.

B). Nunca he tenido ningún problema con Facebook Connect. Todo sigue siendo un código JavaScript simple que se ejecuta en un navegador y undefined===undefined esté donde esté.

En resumen, debe proporcionar evidencia de que su object.x realmente no estaba definido y no es nulo o no, porque creo que es imposible que lo que está describiendo realmente sea el caso, sin ofender :) - Pondría dinero en el problema existente en el código de Tersus.

+1

Gracias, annakata. Tu respuesta escéptica me hizo volver a tratar el tema y encontrar la respuesta correcta (ver abajo). –

15

Es una mala práctica usar el operador de igualdad == en lugar de ===.

undefined === undefined // true 
null == undefined // true 
null === undefined // false 

El object.x === undefined debería devolver true si x es propiedad desconocida.

En el capítulo Bad Parts of JavaScript: The Good Parts, Crockford escribe lo siguiente:

If you attempt to extract a value from an object, and if the object does not have a member with that name, it returns the undefined value instead.

In addition to undefined, JavaScript has a similar value called null. They are so similar that == thinks they are equal. That confuses some programmers into thinking that they are interchangeable, leading to code like

value = myObject[name]; 
if (value == null) { 
    alert(name + ' not found.'); 
} 

It is comparing the wrong value with the wrong operator. This code works because it contains two errors that cancel each other out. That is a crazy way to program. It is better written like this:

value = myObject[name]; 
if (value === undefined) { 
    alert(name + ' not found.'); 
} 
+0

¿Alguna vez has leído esta maravillosa pieza: http://webreflection.blogspot.ie/2010/10/javascript-coercion-demystified.html? – op1ekun

18

me gustaría publicar alguna información importante acerca de undefined, que los principiantes no conozcan.

Mira el siguiente código:

/* 
    * Consider there is no code above. 
    * The browser runs these lines only. 
    */ 

    // var a; 
    // --- commented out to point that we've forgotten to declare `a` variable 

    if (a === undefined) { 
     alert('Not defined'); 
    } else { 
     alert('Defined: ' + a); 
    } 

    alert('Doing important job below'); 

Si ejecuta este código, en donde la variable a nunca ha sido declarado usando var, obtendrá un error de excepción y sorprendentemente ver ninguna alerta en absoluto.

En lugar de 'Hacer un trabajo importante a continuación', su script se TERMINARÁ INESPERADAMENTE, lanzando una excepción no controlada en la primera línea.


Aquí es el único modo a prueba de balas para comprobar si hay undefined usando typeof palabra clave, que fue diseñado sólo para tal fin:

/* 
    * Correct and safe way of checking for `undefined`: 
    */ 

    if (typeof a === 'undefined') { 
     alert(
      'The variable is not declared in this scope, \n' + 
      'or you are pointing to unexisting property, \n' + 
      'or no value has been set yet to the variable, \n' + 
      'or the value set was `undefined`. \n' + 
      '(two last cases are equivalent, don\'t worry if it blows out your mind.' 
      ); 
    } 

    /* 
    * Use `typeof` for checking things like that 
    */ 

Este método funciona en todos los casos posibles.

El último argumento de utilizarlo es que undefined puede ser potencialmente sobreescriben en versiones anteriores de Javascript:

 /* @ Trollface @ */ 
     undefined = 2; 
    /* Happy debuging! */ 

esperanza era lo suficientemente clara.

+0

'función xx (a) {if (a === undefined) a = 'default'; } xx() '- esta es una buena manera de organizar argumentos predeterminados en javascript – Dan

4
var a; 

typeof a === 'undefined'; // true 
a === undefined; // true 
typeof a === typeof undefined; // true 
typeof a === typeof sdfuwehflj; // true 
+0

+1 mejor respuesta !!! – coolguy

10

De - JQuery_Core_Style_Guidelines

  • variables globales:
    typeof variable === "undefined"

  • variables locales:
    variable === undefined

  • Propiedades:
    object.prop === undefined

+1

Solo una nota: si una variable no existe en absoluto, no es local ni global. Lo que no es tan intuitivo es que deberíamos verificar esas variables potencialmente inexistentes de la misma manera que verificamos las variables globales, como Dan nos mostró en su ejemplo. – JustAMartin