Diferencias entre == y === (comparaciones en JavaScript)

57

12

Siempre he visto que en JavaScript hay:

  • asignaciones =
  • comparaciones == y ===

Creo entender que == hace algo parecido a comparar el valor de la variable y el === también compara el tipo (como un equals de java).

¿Alguien podría confirmarme este punto y extenderlo?. Soy javero y el no tipado de javascript a veces me encanta y otras lo odio.


¿Cuál es la manera correcta en javascript de comparar undefined, null y otros valores por defecto?

variable == null
variable === null

¿undefined se usa como cadena de texto o como palabra clave? ¿Cual de las siguientes comparaciones es la correcta para un elemento html sin value? (por ejemplo un label sin contenido)

variable == "undefined"
variable === "undefined"
variable == undefined
variable === undefined

Jordi Castilla

Posted 2015-12-03T09:45:07.097

Reputation: 3 544

Answers

56

Los operadores === y !== son los operadores de comparación estricta. Esto significa que si los operandos tienen tipos diferentes, no son iguales. Por ejemplo,

1 === "1" // false
1 !== "1"  // true
null === undefined // false

Los operadores == y != son los operadores de comparación relajada. Es decir, si los operandos tienen tipos diferentes, JavaScript trata de convertirlos para que fueran comparables. Por ejemplo,

1 == "1" // true
1 != "1" // false
null == undefined // true

Vale mencionar que el operador == no es transitivo, al contrario que ===.

"0" == 0 // true
0 == ""  // true
"0" == ""// false

No es muy fácil recordar todas las reglas de la comparación relajada, y a veces funciona en una manera contraintuitiva. Por eso, yo recomiendo usar === en vez de ==.

No recuerdo todos los pequeños detalles del operador ==, entonces echemos un vistazo a la especificación, punto 11.9.3:

El algoritmo de la comparación de igualdad abstracta

La comparación x == y, donde x e y son valores, regresa true o false. Esta comparación se realiza de la siguiente manera:

  1. Si Type(x) y Type(y) son los mismos,
    1. Si Type(x) es Undefined, regresa true.
    2. Si Type(x) es Null, regresa true.
    3. Si Type(x) es Number,
      1. Si x es NaN, regresa false.
      2. Si y es NaN, regresa false.
      3. Si x es el mismo valor de Number que y, regresa true.
      4. Si x es +0 e y es −0, regresa true.
      5. Si x es -0 e y es +0, regresa true.
      6. Regresa false.
    4. Si Type(x) es String, regresa true si x e y son exactamente la misma secuencia de caracteres (con la misma longitud y los mismos caracteres en las posiciones correspondientes). En el caso contrario, regresa false.
    5. Si Type(x) es Boolean, regresa true, si x e y ambos son true o ambos son false. En el caso contrario, regresa false.
    6. Regresa true si x e y refieren al mismo objeto. En el caso contrario, regresa false.
  2. Si x es null e y es undefined, regresa true.
  3. Si x es undefined e y es null, regresa true.
  4. Si Type(x) es Number y Type(y) es String,
    regresa el resultado de la comparación x == ToNumber(y).
  5. Si Type(x) es String y Type(y) es Number,
    regresa el resultado de la comparación ToNumber(x) == y.
  6. Si Type(x) es Boolean, regresa el resultado de la comparación ToNumber(x) == y.
  7. Si Type(y) es Boolean, regresa el resultado de la comparación x == ToNumber(y).
  8. Si Type(x) es String o Number, y Type(y) es Object,
    regresa el resultado de la comparación x == ToPrimitive(y).
  9. Si Type(x) es Object y Type(y) es String o Number,
    regresa el resultado de la comparación ToPrimitive(x) == y.
  10. Regresa false.

Esta respuesta es una traducción de mi respuesta a la misma pregunta en el sitio ruso.

Peter Olson

Posted 2015-12-03T09:45:07.097

Reputation: 2 135

31

Efectivamente == compara valor, mientras que === compara también tipo. Por ejemplo.

"1" == 1 // true
"1" === 1 // false
null == undefined // true
null === undefined // false

Puedes leer los detalles técnicos (en inglés) en Equality comparisons and sameness

undefined es una palabra reservada y se usa sin comillas.

afgomez

Posted 2015-12-03T09:45:07.097

Reputation: 427

27

La diferencia es que == primero intenta convertir los tipos antes de compararlos. El operador === no, hace una comparación directa aunque siempre retorna falso si los tipos son diferentes. fuente (en inglés)

ej:

1 == "1" // verdadero    
1 === "1" // falso
'' == 0 // verdadero
'' === 0 // falso

Estos gráficos quizá puedan ayudarte a visualizar la diferencia:

Operador '=='

introducir la descripción de la imagen aquí

Operador '==='

introducir la descripción de la imagen aquí

(fuente de las imágenes)

Emanuel Ve

Posted 2015-12-03T09:45:07.097

Reputation: 13 498

21

No exactamente. Es verdad que el operador === compara el tipo y el valor, sin hacer conversiones como haría el operador ==. Sin embargo eso solo es cierto para tipos de valor. En los tipos por referencia lo que hace es comprobar que es el mismo objeto, no basta con que sea del mismo tipo y valor. Así que === sería un operador de identidad, al contrario que ==.

Por ejemplo:

var a = { x: 1, y: 2 };
var b = { x: 1, y: 2 };
var c = a;

a === b  // false
a === c  // true

El caso de las cadenas funcionaría como un tipo de valor, a no ser que usaras el constructor String, que sería un tipo de referencia.

Señalar también que el operador == no es transitivo en algunas conversiones. Por ejemplo:

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

Dada la ambigüedad de este operador, se aconseja que se use el operador === siempre que sea posible.

En todo caso puedes echar un vistazo a esta página que resolverá dudas respecto a ambos operadores. Ahí puedes comprobar entre otras cosas que undefined == null pero undefined !== null.

Guillermo Ruiz

Posted 2015-12-03T09:45:07.097

Reputation: 614

gracias guillermo! lo que no acabo de entender es porque a === b es false....Jordi Castilla 2015-12-03T10:48:24.300

Al ejemplo de transitividad le falta un caso: '0' == 0 // true (y mover el primer caso al último lugar)Alvaro Montoro 2015-12-03T15:28:20.367

@JordiCastilla eso ocurre porque JavaScript tiene dos maneras diferentes de comparar: en el caso de las primitivas (ej: int, string) se compara el valor, mientras que en el caso de los objetos (ej: date, array, u objetos definidos por el usuario) lo que se compara es la referencia y lo que se comprueba es que estén en la misma posición de memoria. Por eso cuando se compara a con c el resultado es true.Alvaro Montoro 2015-12-03T15:35:09.653

2@JordiCastilla a === b es false porque a y b no apuntan al mismo objeto... apuntan a objetos diferentes cuyas propiedades da la casualidad de que tienen los mismos valoresJcl 2015-12-03T18:16:41.353

Vale mencionar que a == b también es false.Peter Olson 2015-12-04T00:40:12.843

7

Bien sencillo

== es igualdad de valor y no de tipo.
=== es igualdad de valor y tipo.

1 == '1'  // true
1 === '1' // false, ya que uno es un string.
1 === 1   // son iguales 

Infraganti

Posted 2015-12-03T09:45:07.097

Reputation: 165

7

Ya te han contestado correctamente la pregunta, pero me gustaría hacer un comentario en lo que parece ser tu problema (yo también empece con java y hay ciertas cosas que javascript facilita).

Una variable puede tener 2 estados, "undefined" o tener algo, null como en SQl es un tipo de valor, es decir que si tu variable tiene null esta definida y tiene algo, nada pero algo :P , undefined quiere decir que tu variable no ha sido definida, es curioso ese hecho sobre todo por que null == undefined responde true.

Ahora cuando tu buscas un elemento con js y no lo encuentra (por ejemplo document.getElementById("inpt")) su valor es null, en el caso que si lo encuentre preguntas por su value y en caso de no tenerlo te responde "".

La parte interesante es que con un simple if resuelves mucho.

var una,dos = null,tres =[],cuatro = 1;

if(noexisto) //es undefinided, saca error por que estas preguntando por ella
if( typeof notoy == "undefined") //es la manera correcta de preguntar si una variable no ha sido definida
if(una)//false pero no saca error por que implicitamente tiene un null
if(una == null) //es lo mismo que la anterior
if(dos) //false pero no saca error
if(tres) //true por que contiene un array, vacio pero es algo
if("")//false por que esta vacio
if(cuatro)//tiene algo por tanto es true

phipex

Posted 2015-12-03T09:45:07.097

Reputation: 181

2

En caso de no transpilar tu código JS (con Babel por ejemplo) la operación "==" es más rápida que la comprobación de tipo con "===" por lo tanto si tu código va a ser útilizado en muchas ocasiones (es parte de la arquitectura o alguna librería) es preferible usar "==" teniendo en cuenta que no vas a pasar un filtro de tipo. En el resto de ocasiones (la gran mayoría) es mejor utilizar la comprobación de tipos con "===" para evitar resultados inesperados.

Luis Resco

Posted 2015-12-03T09:45:07.097

Reputation: 21

1Voy a aportar un poco más de verdad sobre la comparación de "==" y "===". Es sorprendente pero si haces unas pruebas de rendimiento la triple comparación es un 10% más rápida en la mayoría de casos que la doble. También, en el caso de comparar un "number" con un "string" que debemos transformar a "number" para poder realizar la comparación, el proceso se alarga unas 20 veces.

if ( +"1" === 1) { // Código }

Por lo tanto, para evitar grandes problemas de rendimiento es siempre recomendable usar "===" en todos los casos para forzarnos a escribir mejor código y respetar los tipos. – Luis Resco 2016-12-27T14:23:44.943