JSLint esperaba '===' y en su lugar vio '=='

90

Recientemente, estaba ejecutando parte de mi código a través de JSLint cuando se me ocurrió este error. Sin embargo, lo que creo que es gracioso acerca de este error es que automáticamente asume que todos == deberían ser ===.

¿Eso realmente tiene algún sentido? Pude ver muchos casos en los que no querría comparar el tipo y me preocupa que esto realmente pueda causar problemas.

La palabra "esperado" implicaría que esto debería hacerse CADA vez ..... Eso es lo que no tiene sentido para mí.

Metrópoli
fuente
7
También me encontré con esto con JSLint. Hice una actualización de == a === y en realidad rompió el código que funcionaba anteriormente.
kemiller2002
5
Si su código tiene más de 100 líneas, no pasará jslint, de verdad, es imposible.
3
"Rompió" es una palabra demasiado fuerte. Cambió el significado de su código. Si estuvieras haciendo una myVar == nullverificación, sí, grandes cambios. ; ^) El argumento de Crockford es que hizo que el significado del código fuera más preciso, y eso es difícil de argumentar.
ruffin

Respuestas:

127

En mi opinión, usar ciegamente ===, sin tratar de entender cómo funciona la conversión de tipos , no tiene mucho sentido.

El temor principal sobre el operador Equals ==es que las reglas de comparación que dependen de los tipos comparados pueden hacer que el operador no sea transitivo, por ejemplo, si:

A == B AND
B == C

Realmente no garantiza que:

A == C

Por ejemplo:

'0' == 0;   // true
 0  == '';  // true
'0' == '';  // false

El operador Strict Equals ===no es realmente necesario cuando compara valores del mismo tipo, el ejemplo más común:

if (typeof foo == "function") {
  //..
}

Comparamos el resultado del typeofoperador, que siempre es una cadena , con un literal de cadena ...

O cuando conozca las reglas de coerción de tipos, por ejemplo, verifique si algo es nullo undefinedalgo:

if (foo == null) {
  // foo is null or undefined
}

// Vs. the following non-sense version:

if (foo === null || typeof foo === "undefined") {
  // foo is null or undefined
}
Christian C. Salvadó
fuente
1
Odio esta regla de JSLint. Creo que el problema real es que la gente no debería usar operadores de formas que no entiendan (irónicamente, estas son a menudo el mismo tipo de personas que reemplazarían ciegamente '===' con '=='). Claro, hay algunos casos habituales que surgen al comparar el número 0 con varias cadenas, pero si está comparando datos no relacionados como 0 == 'esto es una cadena', ¡su código probablemente tenga problemas más grandes que el doble de igual! Si sabe con certeza con qué tipos está tratando y sabe exactamente cómo interactúan con ==, entonces creo que debería usarlo.
Jon
3
@Jon El punto del ===operador es la claridad del código. No existe una situación razonable para usar, ==ya que nunca será tan clara y comprensible como el operador de identidad. No se trata de si entiendes a los operadores o no, se trata de usar el que hace que tu código sea más fácil de leer sin costo alguno. Los únicos desarrolladores que se oponen al operador de identidad son los desarrolladores individuales y las personas que no trabajan en equipo. Por definición, las personas cuyo código no es revisado por suficientes ojos.
Alternatex
2
Encuentro que la comparación == nula es casi esencial. El problema se vuelve aún menos importante si su código está bien probado.
Jon
1
De hecho, hay ocasiones en las que usar == es esencial para realizar la prueba requerida. si foo.toString () funcionará de manera predecible y una cadena simple necesita ser probada contra esa salida, entonces escribir foo == stringToTest es mucho más limpio que foo.toString () === stringToTest.
Crispen Smith
2
@Alternatex ¡Si el punto era la claridad, no deberían haberlo hecho TRIPLE igual! Ningún principiante lo entiende. Se conoce al menos doble igual en otros idiomas. Además, there is no reasonable situationes un error grave. Piense en los tipos de JavaScript (nativos) Numbery String. Su existencia demuestra que los autores de Javascript tenían en mente ciertos casos de uso ==. ¿De verdad crees que new String('hi') === 'hi'evaluar a falsees muy claro? Escriba un fragmento de código que pruebe el argumento de su función en contra de 'hi'aceptar tanto String como String y dígame que está claro.
Stijn de Witt
25

JSLint es inherentemente más defensivo de lo que permite la sintaxis de Javascript.

De la documentación de JSLint:

Los operadores ==y !=escriben coerción antes de comparar. Esto es malo porque causa ' \t\r\n' == 0que sea verdad. Esto puede enmascarar errores de tipo.

Al comparar con cualquiera de los siguientes valores, use los operadores ===o !==(que no utilizan coerción de tipos):0 '' undefined null false true

Si solo le importa que un valor sea verdadero o falso , utilice la forma abreviada. En vez de

(foo != 0)

sólo decir

(foo)

y en lugar de

(foo == 0)

decir

(!foo)

Se prefieren los operadores ===y !==.

Daniel Vandersluis
fuente
8
Tengo que concluir que la gente de JSLint trabaja en una torre de marfil muy alta de la que nunca salen. Javascript fue diseñado para ser utilizado con el ==operador. El ===es un caso especial ... JSLint intenta hacer parecer que el uso de ==alguna manera sería mal ... Sin embargo, intente lo siguiente: var x = 4, y = new Number(4); if (x == y) {alert('Javascript depends on == just embrace it!');}. Los tipos primitivos tienen clases correspondientes que los sustituyen ( Number, String) y Javascript depende del ==operador para que compararlos sea natural.
Stijn de Witt
17

Tenga en cuenta que JSLint refuerza la idea de una persona de lo que debería ser un buen JavaScript. Aún debe usar el sentido común al implementar los cambios que sugiere.

En general, comparar el tipo y el valor hará que su código sea más seguro (no se encontrará con el comportamiento inesperado cuando la conversión de tipos no haga lo que usted cree que debería hacer).

Justin Niessner
fuente
4
Además, no puede ser tan inteligente en contexto como un programador. Simplemente funciona sobre la base de que la mayoría de los usuarios se tropiezan con la conversión automática de tipos inherente al sistema (como la violencia, "¡ayuda, ayuda, estoy siendo reprimido!")
Rudu
14

Triple-igual es diferente a doble-igual porque además de verificar si los dos lados tienen el mismo valor, triple-igual también verifica que sean del mismo tipo de datos.

Entonces ("4" == 4)es cierto, mientras que ("4" === 4)es falso.

Triple-equal también se ejecuta un poco más rápido, porque JavaScript no tiene que perder tiempo haciendo conversiones de tipo antes de darle la respuesta.

JSLint tiene como objetivo deliberadamente hacer que su código JavaScript sea lo más estricto posible, con el objetivo de reducir errores oscuros. Destaca este tipo de cosas para intentar que codifique de una manera que lo obligue a respetar los tipos de datos.

Pero lo bueno de JSLint es que es solo una guía. Como dicen en el sitio, herirá tus sentimientos, incluso si eres un muy buen programador de JavaScript. Pero no debe sentirse obligado a seguir sus consejos. Si ha leído lo que tiene que decir y lo entiende, pero está seguro de que su código no se romperá, entonces no hay obligación de cambiar nada.

Incluso puede decirle a JSLint que ignore las categorías de comprobaciones si no quiere ser bombardeado con advertencias sobre las que no va a hacer nada.

Spudley
fuente
3
No pregunté "¿Qué es ===?", Así que no estoy seguro de por qué lo respondió.
Metropolis
8
@Metropolis: si no es por otra razón, entonces como antecedente en caso de que alguien más lea la respuesta que no lo sabía. Sin embargo, intenté responder a tu pregunta en los párrafos siguientes.
Spudley
@Spudley + 1 para obtener información adicional y útil
Ben Junior
1
sí, es 10-100 veces más rápido: prueba de velocidad
jsperf
8

Una cita de http://javascript.crockford.com/code.html :

=== y! == Operadores.

Casi siempre es mejor utilizar los operadores === y! ==. Los operadores == y! = Escriben coerción. En particular, no use == para comparar con valores falsos.

JSLint es muy estricto, su 'webjslint.js' ni siquiera pasa su propia validación.

Lekensteyn
fuente
Buena aclaración. Eso es cierto, sobre webjslint.jsno validar, aunque la mayoría de los errores que veo ahora tienen que ver con el espaciado. Claramente, uno debe usar el sentido común y el juicio razonable al revisar JavaScript usando JSLint.
hotshot309
El uso de la palabra alwaysautomáticamente descalifica esta cita como sabiduría. Los programadores inteligentes no son dogmáticos. Usan lo que es mejor en la situación dada. Y dan la bienvenida y adoptan cualquier herramienta integrada en el núcleo del lenguaje, no solo la descartan con un just never touch it. En pocas palabras: mi código es más corto (y no solo por guardar un =carácter), por lo que mi sitio se carga más rápido, con un menor costo de ancho de banda, por lo que mi usuario está mejor atendido.
Stijn de Witt
4

Si quieres probar la falsedad. JSLint no permite

if (foo == null)

pero permite

if (!foo)
nano2nd
fuente
Use ===, que JSLint recomienda.
clickbait
1
@NarawaGames Esta solución es perfectamente aceptable.
Esta respuesta no es buena. El caso es que ambos significan algo más. foo == nullcomprueba si es nulo o indefinido. !foocomprueba si hay cadenas nulas, indefinidas, 0 y vacías.
Markos
@Markos Esta respuesta está destinada a ser una alternativa útil para hacer feliz a JSLint y mantener intacta la lógica de su código, no para ser un equivalente exacto. Es por eso que prefijé la respuesta con "Si se verifica la falsedad"
nano2nd
3

Para ayudar a explicar esta pregunta y también explicar por qué NetBeans (de) 7.3 ha comenzado a mostrar esta advertencia, este es un extracto de la respuesta en el rastreador de errores de NetBeans cuando alguien informó esto como un error:

Es una buena práctica utilizar === en lugar de == en JavaScript.

Los operadores == y! = Escriben coerción antes de comparar. Esto es malo porque hace que '\ t \ r \ n' == 0 sea cierto. Esto puede enmascarar errores de tipo. JSLint no puede determinar de manera confiable si == se está usando correctamente, por lo que es mejor no usar == y! = En absoluto y siempre usar los operadores === y! == más confiables en su lugar.

Referencia

Creaciones EM
fuente
1
Encontré este error ahora usando Netbeans también. Es extraño que traten esto con severidad de advertencia debido al extraño caso de ejemplo que proporcionaron.
omikes el
1
Quiero decir, es cierto, pero hay muchos casos de uso en los que la persona sabe que las dos cosas comparadas serán del mismo tipo, por lo que parece extraño que debido a este extraño caso en el que un retorno de carro pueda compararse con el número cero es la razón por la que todos los usos de == se consideran incorrectos. Sin embargo, estoy descubriendo que === es más rápido, ya que no se realizan conversiones de tipo. Me sorprende no haber descubierto esto antes de netbeans.
omikes
@oMiKeY Sí, veo lo que quieres decir, ¡podrían haber dado ejemplos más realistas!
EM-Creations
2

Bueno, realmente no puede causar problemas, solo te está dando un consejo. Tómelo o déjelo. Dicho esto, no estoy seguro de lo inteligente que es. Bien puede haber contextos en los que no lo presente como un problema.

Rushyo
fuente
1
pero ¿por qué se usa la palabra "esperado"? Eso hace que parezca que siempre debes hacer esto.
Metropolis
4
El evaluador está buscando una respuesta válida, ya que está tratando de validarla. Si no obtiene una respuesta válida, entonces no es lo que esperaba. El validador comienza con la suposición de que todo está bien y luego señala los errores a medida que atraviesa el código. No comprende necesariamente qué es una respuesta inválida, solo sabe cuándo ve una no válida. También podría funcionar a la inversa, buscando deliberadamente código incorrecto de acuerdo con las reglas de lo que es malo. Lista blanca vs lista negra.
Rushyo
La pregunta era "¿Eso realmente tiene algún sentido?". Dada esa pregunta, sí, lo hace. Además, fue hace cinco años . Jesús.
Rushyo