117

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
Carlos Muñoz
  • 12,864
  • 2
  • 42
  • 62
Jordi Castilla
  • 7,189
  • 10
  • 35
  • 60

8 Answers8

106

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
  • 4,645
  • 3
  • 18
  • 22
48

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)

rnrneverdies
  • 16,491
  • 3
  • 49
  • 79
37

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
  • 487
  • 3
  • 4
29

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
  • 816
  • 7
  • 4
  • gracias guillermo! lo que no acabo de entender es porque `a === b` es `false`.... – Jordi Castilla Dec 03 '15 at 10:48
  • Al ejemplo de transitividad le falta un caso: `'0' == 0 // true` (y mover el primer caso al último lugar) – Alvaro Montoro Dec 03 '15 at 15:28
  • 2
    @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 Dec 03 '15 at 15:35
  • 3
    @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 valores – Jcl Dec 03 '15 at 18:16
  • 1
    Vale mencionar que `a == b` también es `false`. – Peter Olson Dec 04 '15 at 00:40
13

Bien sencillo

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

 console.log("1 == '1   =>", 1 == '1')  // true
 console.log("1 === '1' =>", 1 === '1') // false, ya que uno es un string.
 console.log("1 === 1   =>", 1 === 1)   // son iguales
JackNavaRow
  • 6,836
  • 5
  • 22
  • 49
Pepper 92
  • 405
  • 4
  • 17
8

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
  • 251
  • 3
  • 7
3

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
  • 31
  • 1
  • 1
    Voy 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 Dec 27 '16 at 14:23
1

Aclaremos conceptos:

  • Toda variable en JavaScript tiene un tipo y un valor.

  • En JavaScript existe algo llamado coerción. La coerción es una conversión automática (e implícita) que realiza el motor de JavaScript en un intento de operar con valores de diferente tipo. Por ejemplo:

const valor1 = '5';
const valor2 = 9;
let suma = valor1 + valor2;
console.log(suma);

Como valor1 es de tipo string y valor2 es de tipo number, JavaScript lleva a cabo la conversión automática del segundo valor en un intento de poder realizar la suma. De esta manera, el valor de la variable suma será de tipo string:

'59'

CONCLUSIÓN

El operador == compara dos valores sin tener en cuenta el tipo. Es decir, efectua coerción y entonces compara. Si los valores son iguales tras la conversión, devuele el valor true.

El operador === en cambio devuelve true solo en el caso en el que valor y tipo coincidan.

Aclaración: esto solo aplica a los 6 tipos primitivos.