Comprobación nula de JavaScript

170

Me he encontrado con el siguiente código:

function test(data) {
    if (data != null && data !== undefined) {
        // some code here
    }
}

Soy algo nuevo en JavaScript, pero, por otras preguntas que he estado leyendo aquí, tengo la impresión de que este código no tiene mucho sentido.


En particular, esta respuesta dice que

Obtendrá un error si accede a una variable indefinida en cualquier contexto que no sea typeof.

Actualización: la (cita de) la respuesta anterior puede ser engañosa. Debería decir "una variable no declarada" , en lugar de "una variable indefinida" .

Como descubrí, en las respuestas de Ryan ♦ , maerics y nwellnhof , incluso cuando no se proporcionan argumentos para una función, sus variables para los argumentos siempre se declaran. Este hecho también demuestra que es incorrecto el primer elemento de la lista a continuación.


Según tengo entendido, se pueden experimentar los siguientes escenarios:

  • Se llamó a la función sin argumentos, por lo que se datacreó una variable indefinida y se generó un error data != null.

  • La función se llamó específicamente con null(o undefined), como argumento, en cuyo caso data != nullya protege el código interno, && data !== undefinedinutilizándolo.

  • La función se llamó con un argumento no nulo, en cuyo caso pasará trivialmente ambos data != null y data !== undefined .

P: ¿Es correcto mi entendimiento?


He intentado lo siguiente, en la consola de Firefox:

--
[15:31:31.057] false != null
[15:31:31.061] true
--
[15:31:37.985] false !== undefined
[15:31:37.989] true
--
[15:32:59.934] null != null
[15:32:59.937] false
--
[15:33:05.221] undefined != null
[15:33:05.225] false
--
[15:35:12.231] "" != null
[15:35:12.235] true
--
[15:35:19.214] "" !== undefined
[15:35:19.218] true

No puedo entender un caso en el que el data !== undefined after data != null pueda ser de alguna utilidad.

afsantos
fuente
9
Solo úsalo if (data). Es una forma mnemónica de Javascript para verificar si la datavariable se evalúa como verdadera. undefined, nullfalso, 0, cadena vacía, matriz vacía y objeto (?) sin propiedades se evalúa como falso, el resto es verdadero.
J0HN
20
@ J0HN - Usar if(data)significaría que no puede pasar falseo 0como valores para data.
techfoobar
@ J0HN Además, la misma respuesta que menciono también dice que: if(typeof someUndefVar == whatever) -- worksy if(someUnderVar) -- error.
Afsantos
2
Probablemente se supone que es data !== null && data !== undefined, que es equivalente a lo data != nullque es equivalente a data != undefined. La forma anterior tiende a ser favorecida ya que es más explícita sobre las condiciones, mientras que sería fácil pasar por alto ambas nully undefinedse verificará con las dos condiciones posteriores.
zzzzBov
2
Por cierto, las pruebas explícitas para undefinedIMO son un olor a código. No es una palabra clave protegida como null, es una variable que no está definida. Esto es completamente válido y va a romper su código:undefined = 1
Izkata

Respuestas:

106

Una "variable indefinida" es diferente del valor undefined.

Una variable indefinida:

var a;
alert(b); // ReferenceError: b is not defined

Una variable con el valor undefined:

var a;
alert(a); // Alerts “undefined”

Cuando una función toma un argumento, ese argumento siempre se declara incluso si su valor es undefined, por lo que no habrá ningún error. Sin embargo, tienes razón en ser != nullseguido por !== undefinedser inútil.

Ry-
fuente
32
data !== null && data !== undefinedSin embargo, tendría sentido.
bfavaretto
@bfavaretto: Sí, por lo que en realidad podría ser un error tipográfico. Pero nunca se sabe ...: D
Ry-
1
Justo como pensaba, gracias por la aclaración. Además, no creo que sea un error tipográfico. He ejecutado una búsqueda y recuento en todo el script, y encontró 10 ocurrencias, así que ... Supongo que el autor también necesita aclaraciones sobre esto.
Afsantos
2
Rasca mi comentario anterior: en realidad, data != nullverificaría ambos nully undefined(pero, curiosamente, solo para nully undefined, y no los otros valores falsos).
bfavaretto
90

En JavaScript, nulles un objeto singleton especial que es útil para señalar "sin valor". Puede probarlo en comparación y, como es habitual en JavaScript, es una buena práctica usar el ===operador para evitar la coerción de tipo confusa:

var a = null;
alert(a === null); // true

Como @rynah menciona, "indefinido" es un poco confuso en JavaScript. Sin embargo, siempre es seguro probar si la typeof(x)cadena es "indefinida", incluso si "x" no es una variable declarada:

alert(typeof(x) === 'undefined'); // true

Además, las variables pueden tener el "valor indefinido" si no se inicializan:

var y;
alert(typeof(y) === 'undefined'); // true

Poniendo todo junto, su cheque debería verse así:

if ((typeof(data) !== 'undefined') && (data !== null)) {
  // ...

Sin embargo, dado que la variable "datos" siempre se define ya que es un parámetro de función formal, no es necesario utilizar el operador "typeof" y puede compararlo directamente con el "valor indefinido".

function(data) {
  if ((data !== undefined) && (data !== null)) {
    // ...

Este fragmento equivale a decir "si la función fue llamada con un argumento que está definido y no es nulo ..."

maerics
fuente
55
¿Por qué debería verse así, sin embargo? != nullserá verdadero para todos los valores excepto nully undefined, y estamos seguros de que esta variable se declara. typeofen otras situaciones, incluso puede ser peligroso, ¿qué pasa si escribe mal el nombre de la variable? Eso puede pasar desapercibido durante mucho tiempo porque no hay error.
Ry-
@maerics lo tanto, si he seguido su respuesta correcta, en un cheque nulo como el escenario anterior, que sería no utilizar !=en absoluto, única comparación estricta, !==?
Afsantos
@rynah: No presumo que sé lo suficiente sobre la solución general de OP para saber si una prueba nula es apropiada o no, pero edité para mencionar el hecho de que usar "typeof" es innecesario.
Maerics
@afsantos: en realidad no creo que muchos valores (¿alguno?) se conviertan en nulos; sin embargo, es una buena práctica usar una comparación estricta ( ===) a menos que realmente sepas lo que estás haciendo y quieras una comparación después de la conversión ( ==).
Maerics
1
@Izkata: Descarte cualquier biblioteca que intente redefinir undefined. Además, Safari en el iPad no lo hará bajo ninguna circunstancia. Ni siquiera puedes delete window.undefined.
Ry-
10

En su caso, use data==null(lo cual es cierto SOLO para valores nulos e indefinidos; en la segunda imagen, enfoque en filas / columnas nulo-indefinido)

Aquí tienes todo ( src ):

Si

ingrese la descripción de la imagen aquí

== (su negación ! = )

ingrese la descripción de la imagen aquí

=== (su negación ! == )

ingrese la descripción de la imagen aquí

Kamil Kiełczewski
fuente
8

P: La función se invocó sin argumentos, lo que convierte los datos en una variable indefinida y genera un error en los datos! = Nulo.

A: Sí, datase establecerá en indefinido. Consulte la sección 10.5 Declaración de vinculación de instanciación de la especificación. Pero acceder a un valor indefinido no genera un error. Probablemente esté confundiendo esto con acceder a una variable no declarada en modo estricto que genera un error.

P: La función se llamó específicamente con nulo (o indefinido), como argumento, en cuyo caso data! = Null ya protege el código interno, lo que hace que && data! == indefinido sea inútil.

P: La función se llamó con un argumento no nulo, en cuyo caso pasará trivialmente data! = Null y data! == undefined.

A: correcto. Tenga en cuenta que las siguientes pruebas son equivalentes:

data != null
data != undefined
data !== null && data !== undefined

Consulte la sección 11.9.3 El algoritmo de comparación de igualdad abstracta y la sección 11.9.6 El Algoritmo de comparación de igualdad estricto de la especificación.

nwellnhof
fuente
No estaba confundiendo con variables no declaradas, realmente no sabía cómo funcionaba cuando no se proporcionaban argumentos. Estaba convencido de que eso datano existiría en absoluto, en lugar de establecerlo undefined. Agradezco la aclaración, y esas referencias me ayudaron a comprender con más detalle cómo funcionan ambas igualdades.
Afsantos
3

Creo que probar variables para valores que no esperas no es una buena idea en general. Porque la prueba como su puede considerar como escribir una lista negra de valores prohibidos. ¿Pero qué pasa si olvida enumerar todos los valores prohibidos? Alguien, incluso usted, puede descifrar su código al pasar un valor inesperado. Por lo tanto, un enfoque más apropiado es algo así como la lista blanca: probar variables solo para los valores esperados, no inesperados. Por ejemplo, si espera que el valor de los datos sea una cadena, en lugar de esto:

function (data) {
  if (data != null && data !== undefined) {
    // some code here
    // but what if data === false?
    // or data === '' - empty string?
  }
}

haz algo como esto:

function (data) {
  if (typeof data === 'string' && data.length) {
    // consume string here, it is here for sure
    // cleaner, it is obvious what type you expect
    // safer, less error prone due to implicit coercion
  } 
}

fuente
2

typeof foo === "undefined"es diferente de foo === undefined, nunca los confundas. typeof foo === "undefined"es lo que realmente necesitas. Además, use !==en lugar de!=

Entonces la declaración se puede escribir como

function (data) {
  if (typeof data !== "undefined" && data !== null) {
    // some code here
  }
}

Editar:

No se puede usar foo === undefinedpara variables no declaradas.

var t1;

if(typeof t1 === "undefined")
{
  alert("cp1");
}

if(t1 === undefined)
{
  alert("cp2");
}

if(typeof t2 === "undefined")
{
  alert("cp3");
}

if(t2 === undefined) // fails as t2 is never declared
{
  alert("cp4");
}

fuente
1
De acuerdo, pero la variable se declara en este caso, entonces, ¿cuál es el problema?
Ry-
Personalmente, me parece foo === undefinedpeligroso de usar. Hace que su código falle por la misma condición que estaba tratando de prevenir.
Estoy hablando del argumento de la función en cuestión. Ver también mi otro comentario .
Ry-
1
¿Por qué se rechaza esto? ¡La primera oración es una distinción correcta e importante !
Izkata
1
@Izkata: porque no hay explicación para la declaración inicial. foo === undefinedes perfectamente aceptable en la situación del OP (suponiendo que undefinedno se haya anulado). La respuesta tampoco explica por qué !== debería usarse en lugar de !=.
Matt
1

La forma simple de hacer tu prueba es:

function (data) {
    if (data) { // check if null, undefined, empty ...
        // some code here
    }
}
Kadiri
fuente
55
¿No es esta prueba dependiente del contexto? Quiero decir, si el tipo esperado para dataes una cadena, esta prueba devuelve falso en las cadenas vacías, lo que puede o no ser apropiado (la función podría tratar con la cadena vacía de alguna manera).
afsantos
55
Excepto que si "datos" tiene el valor ""o 0o NaN(u otros) el "si" bloque será omitida; que puede o no ser la intención de OP.
Maerics
Lo siento @afsantos, no vi tu comentario, si quieres obtener información falsa cuando los datos no están definidos, nulo ... excepto cuando la fecha esté vacía, deberás crear otra var toTest = data; con otra prueba después de la primera como: if (toTest == "") {// algún código aquí}
Kadiri
-5
var a;
alert(a); //Value is undefined

var b = "Volvo"; 
alert(b); //Value is Volvo

var c = null;
alert(c); //Value is null
Desbordamiento
fuente
44
Agregue alguna explicación sobre lo que se supone que significa esto.
Ry-
Esto en realidad no comprobar para null.
user4642212