Detectar una propiedad de objeto indefinido

Respuestas:

2681

La forma habitual de verificar si el valor de una propiedad es el valor especial undefined, es:

if(o.myProperty === undefined) {
  alert("myProperty value is the special value `undefined`");
}

Para verificar si un objeto no tiene esa propiedad y, por lo tanto, volverá undefinedde forma predeterminada cuando intente acceder a él:

if(!o.hasOwnProperty('myProperty')) {
  alert("myProperty does not exist");
}

Para verificar si el valor asociado con un identificador es el valor especial undefined, o si ese identificador no ha sido declarado. Nota: este método es la única forma de referirse a un identificador no declarado (nota: diferente de tener un valor de undefined) sin un error temprano:

if(typeof myVariable === 'undefined') {
  alert('myVariable is either the special value `undefined`, or it has not been declared');
}

En las versiones de JavaScript anteriores a ECMAScript 5, la propiedad denominada "indefinido" en el objeto global era grabable y, por lo tanto, una comprobación simple foo === undefinedpodría comportarse inesperadamente si se hubiera redefinido accidentalmente. En JavaScript moderno, la propiedad es de solo lectura.

Sin embargo, en JavaScript moderno, "indefinido" no es una palabra clave, por lo que las variables dentro de las funciones pueden denominarse "indefinido" y sombrear la propiedad global.

Si le preocupa este caso límite (poco probable), puede usar el operador nulo para obtener el undefinedvalor especial en sí:

if(myVariable === void 0) {
  alert("myVariable is the special value `undefined`");
}
Ry-
fuente
99
si algo es nulo, se define (como nulo), pero puede conjugar las verificaciones también. El detalle molesto del código anterior es que no puede definir una función para verificarla, bueno, puede definir la función ... pero intente usarla.
neu-rah
55
@ neu-rah ¿por qué no puedes escribir una función? ¿Por qué no funcionaría algo como esto? Parece funcionar para mí ¿Hay algún caso que no esté considerando? jsfiddle.net/djH9N/6
Zack
77
@Zack Sus pruebas para isNullorUndefined no consideraron el caso en el que llama a isNullOrUndefined (f) yf no está declarado (es decir, donde no hay una declaración "var f").
pnkfelix
109
Bla, miles de votos ahora. Esta es la peor forma posible de hacerlo. Espero que los transeúntes vean este comentario y decidan revisar ... ejem ... otras respuestas.
Ry-
17
Puedes usar obj !== undefinedahora. undefinedsolía ser mutable, como undefined = 1234lo que causaría resultados interesantes. Pero después de Ecmascript 5, ya no se puede escribir, por lo que podemos usar la versión más simple. codereadability.com/how-to-check-for-undefined-in-javascript
Bruno Buccolo
899

Creo que hay varias respuestas incorrectas a este tema. Contrariamente a la creencia común, "indefinido" no es una palabra clave en JavaScript y, de hecho, puede tener un valor asignado.

Código correcto

La forma más sólida de realizar esta prueba es:

if (typeof myVar === "undefined")

Esto siempre devolverá el resultado correcto, e incluso maneja la situación donde myVar no se declara.

Código degenerado NO UTILICE.

var undefined = false;  // Shockingly, this is completely legal!
if (myVar === undefined) {
    alert("You have been misled. Run away!");
}

Además, myVar === undefinedgenerará un error en la situación donde myVar no está declarado.

MarkPflug
fuente
133
+1 por notar que myVar === undefined generará un error si no se declaró myVar
Enrique
73
Encuentro la primera justificación dada aquí para no usar === undefineddesconcertante. Sí, puede asignar a undefined, pero no hay una razón legítima para hacerlo, y es previsible que hacerlo pueda romper su código. En C puede #define true false, y en Python puede asignar Truey False, pero las personas no sienten la necesidad de diseñar su código en esos lenguajes de tal manera que se proteja contra la posibilidad de sabotear deliberadamente su propio entorno en otra parte del código. . ¿Por qué vale la undefinedpena considerar la posibilidad de asignar aquí?
Mark Amery el
19
Además de los comentarios de Marks, no entiendo esto: "myVar === undefined generará un error en la situación en la que myVar no está declarado". - ¿Por qué es esto malo? ¿Por qué no querría tener un error si estoy haciendo referencia a variables no declaradas?
Eis
55
También tenga en cuenta que siempre puede hacer void 0para obtener el valor que undefinedapunta. Entonces puedes hacerlo if (myVar === void 0). el 0no es especial, puede poner literalmente cualquier expresión allí.
Claudiu
28
En los navegadores modernos (FF4 +, IE9 +, Chrome desconocido), ya no es posible modificarlo undefined. MDN: indefinido
usuario247702
228

A pesar de ser recomendado vehementemente por muchas otras respuestas aquí, typeof es una mala elección . Nunca debe usarse para verificar si las variables tienen el valor undefined, porque actúa como una verificación combinada del valor undefinedy si existe una variable. En la gran mayoría de los casos, usted sabe cuándo existe una variable y typeofsolo presentará la posibilidad de una falla silenciosa si comete un error tipográfico en el nombre de la variable o en la cadena literal 'undefined'.

var snapshot = …;

if (typeof snaposhot === 'undefined') {
    //         ^
    // misspelled¹ – this will never run, but it won’t throw an error!
}
var foo = …;

if (typeof foo === 'undefned') {
    //                   ^
    // misspelled – this will never run, but it won’t throw an error!
}

Entonces, a menos que esté haciendo la detección de características², donde hay incertidumbre sobre si un nombre dado estará dentro del alcance (como verificar typeof module !== 'undefined'como un paso en el código específico de un entorno CommonJS), typeofes una elección dañina cuando se usa en una variable, y la opción correcta es para comparar el valor directamente:

var foo = …;

if (foo === undefined) {
    
}

Algunos conceptos erróneos comunes sobre esto incluyen:

  • que la lectura de una variable (no inicializada var foo) ( ) o parámetro ( function bar(foo) { … }, llamado como bar()) fallará. Esto simplemente no es cierto: las variables sin inicialización explícita y los parámetros a los que no se les dieron valores siempre se convierten undefined, y siempre están dentro del alcance.

  • eso undefinedpuede sobrescribirse. Hay mucho más en esto. undefinedno es una palabra clave en JavaScript. En cambio, es una propiedad en el objeto global con el valor Indefinido. Sin embargo, desde ES5, esta propiedad ha sido de solo lectura y no configurable . Ningún navegador moderno permitirá undefinedque se cambie la propiedad y, a partir de 2017, este ha sido el caso durante mucho tiempo. La falta de modo estricto tampoco afecta undefinedel comportamiento de la persona, solo hace declaraciones como undefined = 5no hacer nada en lugar de tirar. Sin embargo, dado que no es una palabra clave, puede declarar variables con el nombre undefined, y esas variables podrían cambiarse, haciendo este patrón una vez común:

    (function (undefined) {
        // …
    })()

    más peligroso que usar lo global undefined. Si tiene que ser compatible con ES3, reemplácelo undefinedcon void 0- no recurra a él typeof. ( voidsiempre ha sido un operador unario que evalúa el valor Indefinido para cualquier operando).

Con la forma en que las variables funcionan, es hora de abordar la pregunta real: las propiedades del objeto. No hay ninguna razón para usar las typeofpropiedades de objetos. La excepción anterior con respecto a la detección de características no se aplica aquí:typeof solo tiene un comportamiento especial en las variables y las expresiones que hacen referencia a las propiedades del objeto no son variables.

Esta:

if (typeof foo.bar === 'undefined') {
    
}

siempre es exactamente equivalente a esto³:

if (foo.bar === undefined) {
    
}

y teniendo en cuenta los consejos anteriores, para evitar confundir a los lectores en cuanto a por qué está usando typeof, porque tiene más sentido usar ===para verificar la igualdad, porque podría refactorizarse para verificar el valor de una variable más tarde, y porque simplemente se ve mejor, siempre debes usar === undefined³ aquí también .

Otra cosa a tener en cuenta cuando se trata de las propiedades de los objetos es si realmente desea verificarlo undefined. Un nombre de propiedad dado puede estar ausente en un objeto (produciendo el valor undefinedcuando se lee), presente en el objeto mismo con el valor undefined, presente en el prototipo del objeto con el valor undefined, o presente en cualquiera de los que no tienen undefinedvalor. 'key' in objle dirá si una clave está en algún lugar de la cadena de prototipo de un objeto, y Object.prototype.hasOwnProperty.call(obj, 'key')le dirá si está directamente en el objeto. Sin embargo, no entraré en detalles en esta respuesta sobre los prototipos y el uso de objetos como mapas con clave de cadena, porque está destinado principalmente a contrarrestar todos los malos consejos en otras respuestas, independientemente de las posibles interpretaciones de la pregunta original. Leer sobre¡Prototipos de objetos en MDN para más!

¹ elección inusual del nombre de la variable de ejemplo? Este es un código muerto real de la extensión NoScript para Firefox.
² Sin embargo, no asuma que no saber lo que está dentro del alcance está bien en general. vulnerabilidad adicional causada por el abuso del alcance dinámico: Project Zero 1225
³ una vez más asumiendo un entorno ES5 + y que se undefinedrefiere a la undefinedpropiedad del objeto global. sustituto de lo void 0contrario.

Ry-
fuente
@BenjaminGruenbaum Cierto pero completamente engañoso. Cualquier contexto no predeterminado puede definir el suyo undefined, ocultando el predeterminado. Lo que para la mayoría de los propósitos prácticos tiene el mismo efecto que sobreescribirlo.
blgt
23
@blgt Eso es paranoico e irrelevante para cualquier cosa práctica. Cada contexto puede anular console.log, redefinir los métodos de prototipo de Array e incluso anular el enganche Function.prototype.call`, y alterarlo cada vez que llame a una función en JavaScript. Protegerse de esto es muy paranoico y bastante tonto. Como dije (y minitech), puedes usarlo void 0para compararlo con indefinido, pero de nuevo, eso es tonto y excesivo.
Benjamin Gruenbaum
19
Desearía tener más de un voto a favor para dar. Esta es la respuesta más correcta. Realmente quiero dejar de ver typeof something === "undefined") en código.
Simon Baumgardt-Wellander
@BenjaminGruenbaum Para programadores perezosos, ¡ void 0es (por una vez) más corto y más seguro! Eso es una victoria en mi libro.
wizzwizz4
44
Esta realmente debería ser la respuesta aceptada. Es el más completo y actualizado.
Patrick Michaelsen
161

En JavaScript hay nulo y hay indefinido . Tienen diferentes significados.

  • indefinido significa que el valor de la variable no se ha definido; No se sabe cuál es el valor.
  • nulo significa que el valor de la variable está definido y establecido en nulo (no tiene valor).

Marijn Haverbeke afirma, en su libro gratuito en línea " Eloquent JavaScript " (énfasis mío):

También hay un valor similar, nulo, cuyo significado es 'este valor está definido, pero no tiene un valor'. La diferencia de significado entre indefinido y nulo es principalmente académica, y generalmente no muy interesante. En los programas prácticos, a menudo es necesario verificar si algo 'tiene un valor'. En estos casos, se puede usar la expresión algo == undefined, porque, aunque no son exactamente el mismo valor, null == undefined producirá verdadero.

Entonces, supongo que la mejor manera de verificar si algo estaba indefinido sería:

if (something == undefined)

¡Espero que esto ayude!

Editar: en respuesta a su edición, las propiedades del objeto deberían funcionar de la misma manera.

var person = {
    name: "John",
    age: 28,
    sex: "male"
};

alert(person.name); // "John"
alert(person.fakeVariable); // undefined
Pandincus
fuente
42
if (something == undefined) se escribe mejor como if (something === undefined)
Sebastian Rittau el
59
Cabe señalar que esto no es del todo seguro. undefinedes solo una variable que el usuario puede reasignar: la escritura undefined = 'a';hará que su código ya no haga lo que usted cree que hace. Usar typeofes mejor y también funciona para variables (no solo propiedades) que no se han declarado.
Gabe Moothart
77
Si algo es una variable global indefinida, (something == undefined) muestra un error de JavaScript.
Morgan Cheng
8
El problema con esto es que si var a = nulo, entonces a == undefined se evalúa como verdadero, aunque a está definitivamente definido.
Andrew
66
Esta interpretación del comentario "Eloquent Javascript" es al revés . Si realmente solo quiere verificar si está indefinido, el código sugerido no funcionará (también detectará la condición definida pero aún no se ha determinado ningún valor [ienull]). Un valor nulo. El código sugerido "if (something == undefined) ..." verifica tanto undefined como null (sin valor establecido), es decir, se interpreta como "if ((algo está indefinido) OR (algo es nulo)) ..." Lo que dice el autor es que, a menudo, lo que realmente desea es verificar tanto indefinido como nulo.
Chuck Kollars
125

¿Qué significa esto: "propiedad de objeto indefinido" ?

¡En realidad puede significar dos cosas muy diferentes! Primero, puede significar la propiedad que nunca se ha definido en el objeto y, segundo, puede significar la propiedad que tiene un valor indefinido . Veamos este código:

var o = { a: undefined }

Es o.aindefinido? ¡Si! Su valor es indefinido. Es o.bindefinido? ¡Por supuesto! ¡No hay ninguna propiedad 'b' en absoluto! OK, vea ahora cómo se comportan los diferentes enfoques en ambas situaciones:

typeof o.a == 'undefined' // true
typeof o.b == 'undefined' // true
o.a === undefined // true
o.b === undefined // true
'a' in o // true
'b' in o // false

Podemos ver claramente eso typeof obj.prop == 'undefined'y obj.prop === undefinedson equivalentes, y no distinguen esas situaciones diferentes. Y 'prop' in objpuede detectar la situación cuando una propiedad no se ha definido en absoluto y no presta atención al valor de la propiedad que puede estar indefinido.

¿Entonces lo que hay que hacer?

1) Desea saber si una propiedad no está definida por el primer o segundo significado (la situación más típica).

obj.prop === undefined // IMHO, see "final fight" below

2) Solo quiere saber si el objeto tiene alguna propiedad y no le importa su valor.

'prop' in obj

Notas:

  • No puede verificar un objeto y su propiedad al mismo tiempo. Por ejemplo, esto x.a === undefinedo esto typeof x.a == 'undefined'aumenta ReferenceError: x is not definedsi x no está definido.
  • La variable undefinedes una variable global (por lo que window.undefineden realidad está en los navegadores). Se admite desde ECMAScript 1st Edition y desde ECMAScript 5 es de solo lectura . Por lo tanto, en los navegadores modernos no se puede redefinir como verdadero, ya que a muchos autores les encanta asustarnos, pero esto sigue siendo cierto para los navegadores más antiguos.

Pelea final: obj.prop === undefinedvstypeof obj.prop == 'undefined'

Ventajas de obj.prop === undefined:

  • Es un poco más corto y se ve un poco más bonito
  • El motor de JavaScript le dará un error si ha escrito mal undefined

Desventajas de obj.prop === undefined:

  • undefined puede ser anulado en navegadores antiguos

Ventajas de typeof obj.prop == 'undefined':

  • ¡Es realmente universal! Funciona en navegadores nuevos y antiguos.

Desventajas de typeof obj.prop == 'undefined':

  • 'undefned'( mal escrito ) aquí es solo una constante de cadena, por lo que el motor de JavaScript no puede ayudarlo si lo ha escrito mal como lo acabo de hacer.

Actualización (para JavaScript del lado del servidor):

Node.js admite la variable global undefinedcomo global.undefined(también se puede usar sin el prefijo 'global'). No sé sobre otras implementaciones de JavaScript del lado del servidor.

Konstantin Smolyanin
fuente
@ Bergi gracias por tu comentario. He corregido mi respuesta. En mi defensa, puedo decir que actualmente (a partir de v.0.10.18) la documentación oficial de Node.js no dice nada undefinedcomo miembro de global. Además, ni console.log(global);tampoco for (var key in global) { ... }se muestra indefinido como miembro de global . Pero prueba como 'undefined' in globalmuestra lo contrario.
Konstantin Smolyanin
44
No necesitaba documentación adicional ya que está en la especificación EcmaScript , que también dice que [[Enumerable]]es falso :-)
Bergi
55
Al respecto Minuses of typeof obj.prop == 'undefined', esto se puede evitar escribiendo comotypeof obj.prop == typeof undefined . Esto también da una simetría muy agradable.
hlovdal
3
@hlovdal: Eso es totalmente inútil frente obj.prop === undefined.
Ry-
1
Cuando somos fieles al título de la pregunta " Detectar una propiedad indefinida" , no es fiel a la pregunta (diferente y mucho más fácil) en la primera oración ("verificar si no está definida ..."), usted contesta if ('foo' in o) ... su respuesta es realmente la primera respuesta correcta aquí. Casi todos los demás simplemente responden esa oración.
Frank Nocke
70

El problema se reduce a tres casos:

  1. El objeto tiene la propiedad y su valor no lo es undefined.
  2. El objeto tiene la propiedad y su valor es undefined.
  3. El objeto no tiene la propiedad.

Esto nos dice algo que considero importante:

Hay una diferencia entre un miembro indefinido y un miembro definido con un valor indefinido.

Pero, por desgracia typeof obj.foo, no nos dice cuál de los tres casos tenemos. Sin embargo, podemos combinar esto "foo" in objpara distinguir los casos.

                               |  typeof obj.x === 'undefined' | !("x" in obj)
1.                     { x:1 } |  false                        | false
2.    { x : (function(){})() } |  true                         | false
3.                          {} |  true                         | true

Vale la pena señalar que estas pruebas son las mismas para las nullentradas también

                               |  typeof obj.x === 'undefined' | !("x" in obj)
                    { x:null } |  false                        | false

Yo diría que en algunos casos tiene más sentido (y es más claro) verificar si la propiedad está allí, que verificar si no está definida, y el único caso en el que esta verificación será diferente es el caso 2, el caso raro de Una entrada real en el objeto con un valor indefinido.

Por ejemplo: acabo de refactorizar un montón de código que tenía un montón de comprobaciones de si un objeto tenía una propiedad determinada.

if( typeof blob.x != 'undefined' ) {  fn(blob.x); }

Lo cual fue más claro cuando se escribió sin un cheque para indefinido

if( "x" in blob ) { fn(blob.x); }

Pero como se ha mencionado, estos no son exactamente los mismos (pero son más que suficientes para mis necesidades).

Michael Anderson
fuente
10
Hola Michael. Gran sugerencia, y creo que hace las cosas más limpias. Un problema que encontré, sin embargo, es cuando uso el! operador con "en". Tienes que decir if (!("x" in blob)) {}entre paréntesis, porque! el operador tiene prioridad sobre 'in'. Espero que ayude a alguien.
Simon East
Lo siento Michael, pero esto es incorrecto, o al menos engañoso, a la luz de la pregunta original. 'in' no es una forma suficiente de probar si una propiedad de objeto tiene typeof undefined. Para prueba, vea este violín: jsfiddle.net/CsLKJ/4
tex
2
¡Esas dos partes del código hacen algo diferente! Considere y objete dado por a = {b: undefined}; entonces typeof a.b === typeof a.c === 'undefined'pero 'b' in ay !('c' in a).
mgol
3
+1. El OP no deja en claro si la propiedad existe y tiene el valor indefinido , o si la propiedad en sí no está definida (es decir, no existe).
RobG
Sugeriría cambiar el punto (2.) en su primera tabla { x : undefined }o al menos agregarlo como otra alternativa a (2.) en la tabla. Tuve que pensar por un momento para darme cuenta de que el punto (2.) evalúa undefined(aunque Mencionas eso más adelante).
mucaho
46
if ( typeof( something ) == "undefined") 

Esto funcionó para mí mientras que los demás no.

Kevin
fuente
47
los padres son innecesarios ya que typeof es un operador
aehlke
12
Pero aclaran lo que se está comprobando. De lo contrario, podría leerse como typeof (something == "undefined").
Abhi Beckert
Si necesita los paréntesis, debe aprender la precedencia del operador en JS: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Ian
11
Los paréntesis son útiles precisamente porque NO es necesario que aprenda la precedencia del operador en JS, ni necesita especular si los futuros programadores de mantenimiento necesitarán aprender la precedencia del operador en JS.
DaveWalley
27
Los paréntesis son útiles para aclarar cosas. Pero en este caso solo hacen que el operador se vea como una función. Sin duda, esto aclara la intención del programador. Pero si no está seguro acerca de la precedencia del operador, debería escribirlo como (typeof something) === "undefined".
Robert
42

No estoy seguro de que el origen de la utilización ===con typeofvino, y como una convención veo utiliza en muchas bibliotecas, pero el operador typeof devuelve un literal de cadena, y sabemos que por adelantado, así que porqué usted también desea escribir compruebalo tambien?

typeof x;                      // some string literal "string", "object", "undefined"
if (typeof x === "string") {   // === is redundant because we already know typeof returns a string literal
if (typeof x == "string") {    // sufficient
Eric
fuente
Gran punto Eric. ¿Hay un impacto en el rendimiento del tipo de comprobación también?
Simon East
55
@Simon: todo lo contrario: uno podría esperar un ligero impacto en el rendimiento al evitar la coerción en el caso '==='. La prueba rápida y sucia ha demostrado que '===' es un 5% más rápido que '==' en FF5.0.1
Antony Hatchkins
55
Pruebas más exhaustivas han demostrado que bajo FF, IE y Chrome '==' es más o menos rápido que '===' (5-10%) y Opera no hace ninguna diferencia: jsperf.com/triple- equals-vs-twice-equals / 6
Antony Hatchkins
3
El uso ==aún requiere al menos una verificación de tipo: el intérprete no puede comparar los dos operandos sin conocer primero su tipo.
Alnitak
77
==es un personaje menos que ===:)
svidgen
25

Crossposting mi respuesta de la pregunta relacionada ¿ Cómo verificar "indefinido" en JavaScript?

Específico a esta pregunta, ver casos de prueba con someObject.<whatever>.


Algunos escenarios que ilustran los resultados de varias respuestas: http://jsfiddle.net/drzaus/UVjM4/

(Tenga en cuenta que el uso de varfor intests hace la diferencia en un contenedor con ámbito)

Código de referencia:

(function(undefined) {
    var definedButNotInitialized;
    definedAndInitialized = 3;
    someObject = {
        firstProp: "1"
        , secondProp: false
        // , undefinedProp not defined
    }
    // var notDefined;

    var tests = [
        'definedButNotInitialized in window',
        'definedAndInitialized in window',
        'someObject.firstProp in window',
        'someObject.secondProp in window',
        'someObject.undefinedProp in window',
        'notDefined in window',

        '"definedButNotInitialized" in window',
        '"definedAndInitialized" in window',
        '"someObject.firstProp" in window',
        '"someObject.secondProp" in window',
        '"someObject.undefinedProp" in window',
        '"notDefined" in window',

        'typeof definedButNotInitialized == "undefined"',
        'typeof definedButNotInitialized === typeof undefined',
        'definedButNotInitialized === undefined',
        '! definedButNotInitialized',
        '!! definedButNotInitialized',

        'typeof definedAndInitialized == "undefined"',
        'typeof definedAndInitialized === typeof undefined',
        'definedAndInitialized === undefined',
        '! definedAndInitialized',
        '!! definedAndInitialized',

        'typeof someObject.firstProp == "undefined"',
        'typeof someObject.firstProp === typeof undefined',
        'someObject.firstProp === undefined',
        '! someObject.firstProp',
        '!! someObject.firstProp',

        'typeof someObject.secondProp == "undefined"',
        'typeof someObject.secondProp === typeof undefined',
        'someObject.secondProp === undefined',
        '! someObject.secondProp',
        '!! someObject.secondProp',

        'typeof someObject.undefinedProp == "undefined"',
        'typeof someObject.undefinedProp === typeof undefined',
        'someObject.undefinedProp === undefined',
        '! someObject.undefinedProp',
        '!! someObject.undefinedProp',

        'typeof notDefined == "undefined"',
        'typeof notDefined === typeof undefined',
        'notDefined === undefined',
        '! notDefined',
        '!! notDefined'
    ];

    var output = document.getElementById('results');
    var result = '';
    for(var t in tests) {
        if( !tests.hasOwnProperty(t) ) continue; // bleh

        try {
            result = eval(tests[t]);
        } catch(ex) {
            result = 'Exception--' + ex;
        }
        console.log(tests[t], result);
        output.innerHTML += "\n" + tests[t] + ": " + result;
    }
})();

Y resultados:

definedButNotInitialized in window: true
definedAndInitialized in window: false
someObject.firstProp in window: false
someObject.secondProp in window: false
someObject.undefinedProp in window: true
notDefined in window: Exception--ReferenceError: notDefined is not defined
"definedButNotInitialized" in window: false
"definedAndInitialized" in window: true
"someObject.firstProp" in window: false
"someObject.secondProp" in window: false
"someObject.undefinedProp" in window: false
"notDefined" in window: false
typeof definedButNotInitialized == "undefined": true
typeof definedButNotInitialized === typeof undefined: true
definedButNotInitialized === undefined: true
! definedButNotInitialized: true
!! definedButNotInitialized: false
typeof definedAndInitialized == "undefined": false
typeof definedAndInitialized === typeof undefined: false
definedAndInitialized === undefined: false
! definedAndInitialized: false
!! definedAndInitialized: true
typeof someObject.firstProp == "undefined": false
typeof someObject.firstProp === typeof undefined: false
someObject.firstProp === undefined: false
! someObject.firstProp: false
!! someObject.firstProp: true
typeof someObject.secondProp == "undefined": false
typeof someObject.secondProp === typeof undefined: false
someObject.secondProp === undefined: false
! someObject.secondProp: true
!! someObject.secondProp: false
typeof someObject.undefinedProp == "undefined": true
typeof someObject.undefinedProp === typeof undefined: true
someObject.undefinedProp === undefined: true
! someObject.undefinedProp: true
!! someObject.undefinedProp: false
typeof notDefined == "undefined": true
typeof notDefined === typeof undefined: true
notDefined === undefined: Exception--ReferenceError: notDefined is not defined
! notDefined: Exception--ReferenceError: notDefined is not defined
!! notDefined: Exception--ReferenceError: notDefined is not defined
drzaus
fuente
21

Si lo haces

if (myvar == undefined )
{ 
    alert('var does not exists or is not initialized');
}

fallará cuando la variable myvarno exista, porque myvar no está definido, por lo que el script se rompe y la prueba no tiene ningún efecto.

Debido a que el objeto de ventana tiene un alcance global (objeto predeterminado) fuera de una función, se 'adjuntará' una declaración al objeto de ventana.

Por ejemplo:

var myvar = 'test';

La variable global myvar es la misma que window.myvar o window ['myvar']

Para evitar errores de prueba cuando existe una variable global, es mejor usar:

if(window.myvar == undefined )
{ 
    alert('var does not exists or is not initialized');
}

La pregunta si una variable realmente existe no importa, su valor es incorrecto. De lo contrario, es una tontería inicializar variables con indefinido, y es mejor usar el valor falso para inicializar. Cuando sepa que todas las variables que declara se inicializan con falso, simplemente puede verificar su tipo o confiar en !window.myvarque verifique si tiene un valor adecuado / válido. Entonces, incluso cuando la variable no está definida, entonces !window.myvares igual para myvar = undefinedo myvar = falseo myvar = 0.

Cuando espere un tipo específico, pruebe el tipo de la variable. Para acelerar la prueba de una condición, es mejor que lo haga:

if( !window.myvar || typeof window.myvar != 'string' )
{
    alert('var does not exists or is not type of string');
}

Cuando la primera y simple condición es verdadera, el intérprete omite las siguientes pruebas.

Siempre es mejor usar la instancia / objeto de la variable para verificar si tiene un valor válido. Es más estable y es una mejor manera de programar.

(y)

Codebeat
fuente
19

No vi (espero no haberlo extrañado) a nadie revisando el objeto antes de la propiedad. Entonces, este es el más corto y más efectivo (aunque no necesariamente el más claro):

if (obj && obj.prop) {
  // Do something;
}

Si obj u obj.prop no está definido, es nulo o "falso", la instrucción if no ejecutará el bloque de código. Este suele ser el comportamiento deseado en la mayoría de las declaraciones de bloque de código (en JavaScript).

Joe Johnson
fuente
2
Si desea saber por qué esto funciona: Javascript: operadores lógicos y veracidad / falsedad
mb21
si desea asignar la propiedad a una variable si está definida, no es nula y no es falsa, de lo contrario use algún valor predeterminado, puede usar: var x = obj && obj.prop || 'default';
Stijn de Witt
Creo que la pregunta es para verificar explícitamente lo indefinido. Su condición se compara con todos los valores falsos de JS.
NikoKyriakid
15

En el artículo Explorando el abismo de nulo e indefinido en JavaScript , leí que los marcos como Underscore.js usan esta función:

function isUndefined(obj){
    return obj === void 0;
}
Marthijn
fuente
3
void 0es solo una forma corta de escribir undefined(ya que eso es lo que devuelve el vacío seguido de cualquier expresión), guarda 3 caracteres. También podría hacerlo var a; return obj === a;, pero ese es un personaje más. :-)
RobG
2
voides una palabra reservada, mientras undefinedque no es , es decir, mientras que undefinedes igual a void 0por defecto, puede asignar un valor a, undefinedpor ejemplo undefined = 1234.
Brian M. Hunt
isUndefined(obj): 16 caracteres. obj === void 0: 14 caracteres. 'Bastante dicho.
Stijn de Witt el
14

Simplemente cualquier cosa no está definida en JavaScript, está indefinida , no importa si es una propiedad dentro de un objeto / matriz o simplemente como una variable simple ...

JavaScript tiene lo typeofque hace que sea muy fácil detectar una variable indefinida.

Simplemente compruebe si typeof whatever === 'undefined'y devolverá un valor booleano.

Así es como isUndefined()se escribe la famosa función en AngularJs v.1x:

function isUndefined(value) {return typeof value === 'undefined';} 

Entonces, como ve que la función recibe un valor, si ese valor está definido, devolverá false , de lo contrario, para valores indefinidos, devolverá true.

Así que echemos un vistazo a cuáles serán los resultados cuando pasemos valores, incluidas las propiedades de los objetos como a continuación, esta es la lista de variables que tenemos:

var stackoverflow = {};
stackoverflow.javascipt = 'javascript';
var today;
var self = this;
var num = 8;
var list = [1, 2, 3, 4, 5];
var y = null;

y los verificamos a continuación, puede ver los resultados frente a ellos como un comentario:

isUndefined(stackoverflow); //false
isUndefined(stackoverflow.javascipt); //false
isUndefined(today); //true
isUndefined(self); //false
isUndefined(num); //false
isUndefined(list); //false
isUndefined(y); //false
isUndefined(stackoverflow.java); //true
isUndefined(stackoverflow.php); //true
isUndefined(stackoverflow && stackoverflow.css); //true

Como puede ver, podemos verificar cualquier cosa usando algo como esto en nuestro código, como se mencionó, simplemente puede usar typeof en su código, pero si lo está usando una y otra vez, cree una función como la muestra angular que comparto y siga reutilizando como siguiendo el patrón de código DRY.

También una cosa más, para verificar la propiedad de un objeto en una aplicación real que no está seguro, incluso si el objeto existe o no, verifique si el objeto existe primero.

Si marca una propiedad en un objeto y el objeto no existe, arrojará un error y detendrá la ejecución de toda la aplicación.

isUndefined(x.css);
VM808:2 Uncaught ReferenceError: x is not defined(…)

Tan simple que puede envolver dentro de una declaración if como a continuación:

if(typeof x !== 'undefined') {
  //do something
}

Que también es igual a isDefined en Angular 1.x ...

function isDefined(value) {return typeof value !== 'undefined';}

También otros marcos de JavaScript como el subrayado tienen una verificación de definición similar, pero le recomiendo que use typeofsi ya no usa ningún marco.

También agrego esta sección de MDN que tiene información útil sobre typeof, undefined and void (0).

Igualdad estricta e indefinida
Puede usar operadores de igualdad y desigualdad estrictos e indefinidos para determinar si una variable tiene un valor. En el siguiente código, la variable x no está definida y la instrucción if se evalúa como verdadera.

var x;
if (x === undefined) {
   // these statements execute
}
else {
   // these statements do not execute
}

Nota: El operador de igualdad estricta en lugar del operador de igualdad estándar debe usarse aquí, porque x == undefined también verifica si x es nulo, mientras que la igualdad estricta no. nulo no es equivalente a indefinido. Ver operadores de comparación para más detalles.


Tipo de operador e indefinido
Alternativamente, se puede usar typeof:

var x;
if (typeof x === 'undefined') {
   // these statements execute
}

Una razón para usar typeof es que no arroja un error si la variable no ha sido declarada.

// x has not been declared before
if (typeof x === 'undefined') { // evaluates to true without errors
   // these statements execute
}

if (x === undefined) { // throws a ReferenceError

}

Sin embargo, este tipo de técnica debe evitarse. JavaScript es un lenguaje de alcance estático, por lo que saber si se declara una variable puede leerse si se declara en un contexto cerrado. La única excepción es el alcance global, pero el alcance global está vinculado al objeto global, por lo que se puede verificar la existencia de una variable en el contexto global al verificar la existencia de una propiedad en el objeto global (usando el operador in, por ejemplo).


Operador nulo e indefinido

El operador vacío es una tercera alternativa.

var x;
if (x === void 0) {
   // these statements execute
}

// y has not been declared before
if (y === void 0) {
   // throws a ReferenceError (in contrast to `typeof`)
}

más> aquí

Alireza
fuente
13

' if (window.x) {} ' es a prueba de errores

Lo más probable es que quieras if (window.x). Esta comprobación es segura incluso si no se ha declarado x (var x; ): el navegador no arroja un error.

Ejemplo: quiero saber si mi navegador admite API de historial

if (window.history) {
    history.call_some_function();
}

Cómo funciona esto:

La ventana es un objeto que contiene todas las variables globales como sus miembros, y es legal intentar acceder a un miembro no existente. Si x no se ha declarado o no se ha establecido, window.xdevuelve indefinido . undefined conduce a falso cuando if () lo evalúa.

DenisS
fuente
Pero, ¿y si corres en Node? typeof history != 'undefined'en realidad funciona en ambos sistemas.
Stijn de Witt el
13

Al leer esto, me sorprende que no haya visto esto. He encontrado múltiples algoritmos que funcionarían para esto.

Nunca definido

Si el valor de un objeto nunca se definió, esto evitará que regrese truesi se define como nullo undefined. Esto es útil si desea que se devuelva verdadero para los valores establecidos comoundefined

if(obj.prop === void 0) console.log("The value has never been defined");

Definido como indefinido o nunca definido

Si desea que resulte trueen valores definidos con el valor de undefined, o nunca definidos, simplemente puede usar=== undefined

if(obj.prop === undefined) console.log("The value is defined as undefined, or never defined");

Definido como un valor falso, indefinido, nulo o nunca definido.

Comúnmente, la gente me ha pedido un algoritmo para determinar si un valor es falso undefinedo null. Los siguientes trabajos.

if(obj.prop == false || obj.prop === null || obj.prop === undefined) {
    console.log("The value is falsy, null, or undefined");
}
Travis
fuente
44
Creo que puede reemplazar el último ejemplo conif (!obj.prop)
Stijn de Witt
@StijndeWitt, puedes, era bastante inexperto cuando escribí esto, y mi inglés parece haber sido igualmente malo, sin embargo, no hay nada incorrecto en la respuesta
Travis
3
var obj = {foo: undefined}; obj.foo === void 0-> true. ¿Cómo es que "nunca se define como undefined"? Esto está mal.
Patrick Roberts
@PatrickRoberts Tienes razón. Cuando escribí esta respuesta en febrero de 2015 (antes de ES6), la primera opción que describí realmente funcionó, pero ahora está desactualizada.
Travis
12
"propertyName" in obj //-> true | false
sam
fuente
10

Compárese con void 0, para ser conciso.

if (foo !== void 0)

No es tan detallado como if (typeof foo !== 'undefined')

bevacqua
fuente
3
Pero arrojará un ReferenceError si foono está declarado.
daniel1426
1
@ daniel1426: Entonces, si hay un error en tu código, ¿quieres ocultarlo en lugar de arreglarlo? No es un gran enfoque, OMI.
Esto no se usa para ocultar errores. Es la forma común de detectar las propiedades del entorno para definir polyfills. Por ejemplo: if (typeof Promise === 'undefined') {/ * define Promise * /}
gaperton el
10

La solución es incorrecta. En JavaScript

null == undefined

devolverá verdadero, porque ambos están "fundidos" en un booleano y son falsos. La forma correcta sería verificar

if (something === undefined)

cual es el operador de identidad ...

Ricky
fuente
3
Para ser claros, ===es el tipo igualdad + (igualdad primitiva | identidad de objeto), donde las primitivas incluyen cadenas. Creo que la mayoría de las personas consideran 'abab'.slice(0,2) === 'abab'.slice(2)poco intuitivo si uno lo considera ===como el operador de identidad.
clacke
1
Incorrecto. Esto arroja un error si la variable no se ha creado. No debe ser votado. Use typeof en su lugar.
Simon East
10

Puede obtener una matriz totalmente indefinida con la ruta utilizando el siguiente código.

 function getAllUndefined(object) {

        function convertPath(arr, key) {
            var path = "";
            for (var i = 1; i < arr.length; i++) {

                path += arr[i] + "->";
            }
            path += key;
            return path;
        }


        var stack = [];
        var saveUndefined= [];
        function getUndefiend(obj, key) {

            var t = typeof obj;
            switch (t) {
                case "object":
                    if (t === null) {
                        return false;
                    }
                    break;
                case "string":
                case "number":
                case "boolean":
                case "null":
                    return false;
                default:
                    return true;
            }
            stack.push(key);
            for (k in obj) {
                if (obj.hasOwnProperty(k)) {
                    v = getUndefiend(obj[k], k);
                    if (v) {
                        saveUndefined.push(convertPath(stack, k));
                    }
                }
            }
            stack.pop();

        }

        getUndefiend({
            "": object
        }, "");
        return saveUndefined;
    }

Enlace jsFiddle

Anoop
fuente
Si bien no afectará la validez de su código, tiene un error tipográfico: getUndefienddebería serlo getUndefined.
icktoofay
8

Aquí está mi situación:

Estoy usando el resultado de una llamada REST. El resultado debe analizarse desde JSON a un objeto JavaScript.

Hay un error que necesito defender. Si los argumentos de la llamada de descanso fueron incorrectos en la medida en que el usuario especificó los argumentos incorrectos, la llamada de descanso vuelve básicamente vacía.

Mientras usaba esta publicación para ayudarme a defenderme de esto, lo intenté.

if( typeof restResult.data[0] === "undefined" ) { throw  "Some error"; }

Para mi situación, si restResult.data [0] === "objeto", entonces puedo comenzar a inspeccionar con seguridad el resto de los miembros. Si no está definido, arroje el error como se indica arriba.

Lo que digo es que para mi situación, todas las sugerencias anteriores en esta publicación no funcionaron. No digo que tenga razón y todos están equivocados. No soy un maestro de JavaScript en absoluto, pero espero que esto ayude a alguien.

wayneseymour
fuente
Su typeofguardia en realidad no protege contra nada que una comparación directa no pueda manejar. Si restResultno está definido o no está declarado, todavía arrojará.
En su caso, podría simplemente verificar si la matriz está vacía:if(!restResult.data.length) { throw "Some error"; }
Headbank
8

Hay una manera agradable y elegante de asignar una propiedad definida a una nueva variable si está definida o asignarle un valor predeterminado como reserva si no está definida.

var a = obj.prop || defaultValue;

Es adecuado si tiene una función, que recibe una propiedad de configuración adicional:

var yourFunction = function(config){

   this.config = config || {};
   this.yourConfigValue = config.yourConfigValue || 1;
   console.log(this.yourConfigValue);

}

Ahora ejecutándose

yourFunction({yourConfigValue:2});
//=> 2

yourFunction();
//=> 1

yourFunction({otherProperty:5});
//=> 1
Marian Klühspies
fuente
7

Todas las respuestas están incompletas. Esta es la forma correcta de saber que hay una propiedad 'definida como indefinida':

var hasUndefinedProperty = function hasUndefinedProperty(obj, prop){
  return ((prop in obj) && (typeof obj[prop] == 'undefined')) ;
} ;

Ejemplo:

var a = { b : 1, e : null } ;
a.c = a.d ;

hasUndefinedProperty(a, 'b') ; // false : b is defined as 1
hasUndefinedProperty(a, 'c') ; // true : c is defined as undefined
hasUndefinedProperty(a, 'd') ; // false : d is undefined
hasUndefinedProperty(a, 'e') ; // false : e is defined as null

// And now...
delete a.c ;
hasUndefinedProperty(a, 'c') ; // false : c is undefined

Lástima que esta haya sido la respuesta correcta está enterrada en respuestas incorrectas> _ <

Entonces, para cualquiera que pase, ¡te daré indefinidos gratis!

var undefined ; undefined ; // undefined
({}).a ;                    // undefined
[].a ;                      // undefined
''.a ;                      // undefined
(function(){}()) ;          // undefined
void(0) ;                   // undefined
eval() ;                    // undefined
1..a ;                      // undefined
/a/.a ;                     // undefined
(true).a ;                  // undefined
Juan garcia
fuente
7

Revisando los comentarios, para aquellos que desean verificar ambos, está indefinido o su valor es nulo:

//Just in JavaScript
var s; // Undefined
if (typeof s == "undefined" || s === null){
    alert('either it is undefined or value is null')
}

Si está utilizando jQuery Library, jQuery.isEmptyObject()será suficiente para ambos casos,

var s; // Undefined
jQuery.isEmptyObject(s); // Will return true;

s = null; // Defined as null
jQuery.isEmptyObject(s); // Will return true;

//Usage
if (jQuery.isEmptyObject(s)) {
    alert('Either variable:s is undefined or its value is null');
} else {
     alert('variable:s has value ' + s);
}

s = 'something'; // Defined with some value
jQuery.isEmptyObject(s); // Will return false;
Angelin Nadar
fuente
jQuery también se ocupará de cualquier problema de compatibilidad entre navegadores con las diferentes API de JavaScript.
Henry Heleine
7

Si está usando Angular:

angular.isUndefined(obj)
angular.isUndefined(obj.prop)

Underscore.js:

_.isUndefined(obj) 
_.isUndefined(obj.prop) 
Vitalii Fedorenko
fuente
2
¿Cómo agrego 1a la variable x? ¿Necesito subrayar o jQuery? (sorprendente que la gente use las bibliotecas incluso para las operaciones más elementales, como un typeofcheque)
Stijn de Witt
6

Yo uso if (this.variable)para probar si está definido. Simple if (variable), recomendado anteriormente , falla para mí. Resulta que funciona solo cuando variable es un campo de algún objeto, obj.someFieldpara verificar si está definido en el diccionario. Pero podemos usar thiso windowcomo objeto de diccionario, ya que cualquier variable es un campo en la ventana actual, según tengo entendido. Por lo tanto, aquí hay una prueba

if (this.abc) alert("defined"); else alert("undefined");

abc = "abc";
if (this.abc) alert("defined"); else alert("undefined");

Primero detecta que la variable abcno está definida y se define después de la inicialización.

Val
fuente
5

Proporciono tres formas aquí para aquellos que esperan respuestas extrañas:

function isUndefined1(val) {
    try {
        val.a;
    } catch (e) {
        return /undefined/.test(e.message);
    }
    return false;
}
function isUndefined2(val) {
    return !val && val+'' === 'undefined';
}
function isUndefined3(val) {
    const defaultVal={};
    return ((input=defaultVal)=>input===defaultVal)(val);
}
function test(func){
    console.group(`test start :`+func.name);
    console.log(func(undefined));
    console.log(func(null));
    console.log(func(1));
    console.log(func("1"));
    console.log(func(0));
    console.log(func({}));
    console.log(func(function () { }));
    console.groupEnd();
}
test(isUndefined1);
test(isUndefined2);
test(isUndefined3);

isUndefined1:

Intente obtener una propiedad del valor de entrada, verifique el mensaje de error si existe. Si el valor de entrada es indefinido, el mensaje de error sería Tipo de error no capturado: no se puede leer la propiedad 'b' de indefinido

isUndefined2:

Convierta el valor de entrada en una cadena para comparar "undefined"y asegúrese de que sea un valor negativo.

isUndefined3:

En js, el parámetro opcional funciona cuando el valor de entrada es exactamente undefined.

blackmiaool
fuente
5

ES2019 introdujo una nueva característica: encadenamiento opcional que puede usar para usar una propiedad de un objeto solo cuando un objeto se define así:

const userPhone = user?.contactDetails?.phone;

Hará referencia a la propiedad del teléfono solo cuando se definan los detalles de usuario y contacto.

Árbitro. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining

Przemek Struciński
fuente
Solía ​​usar mucho la función get de lodash, muy conveniente para acceder a este tipo de objetos, pero el nuevo encadenamiento opcional cubre la mayoría de los usos de _.get
Al Hill
4
function isUnset(inp) {
  return (typeof inp === 'undefined')
}

Devuelve falso si la variable está establecida, y verdadero si no está definido.

Luego use:

if (isUnset(var)) {
  // initialize variable here
}
Rixius
fuente
55
No. No hagas esto. Solo se necesita una prueba muy simple para demostrar que no se puede ajustar una typeofprueba de manera significativa en una función. Es sorprendente que 4 personas hayan votado por esto. -1.
Stijn de Witt
4

Me gustaría mostrarle algo que estoy usando para proteger la undefinedvariable:

Object.defineProperty(window, 'undefined', {});

Esto prohíbe que cualquiera cambie el window.undefinedvalor, por lo tanto, destruye el código basado en esa variable. Si se usa "use strict", cualquier cosa que intente cambiar su valor terminará en error, de lo contrario se ignoraría en silencio.

Seti
fuente
4

También puede usar Proxy, funcionará con llamadas anidadas, pero requerirá una comprobación adicional:

function resolveUnknownProps(obj, resolveKey) {
  const handler = {
    get(target, key) {
      if (
        target[key] !== null &&
        typeof target[key] === 'object'
      ) {
        return resolveUnknownProps(target[key], resolveKey);
      } else if (!target[key]) {
        return resolveUnknownProps({ [resolveKey]: true }, resolveKey);
      }

      return target[key];
    },
  };

  return new Proxy(obj, handler);
}

const user = {}

console.log(resolveUnknownProps(user, 'isUndefined').personalInfo.name.something.else); // { isUndefined: true }

así que lo usarás como:

const { isUndefined } = resolveUnknownProps(user, 'isUndefined').personalInfo.name.something.else;
if (!isUndefined) {
  // do someting
}
Sarkis Arutiunian
fuente