==, === y typeof en JavaScript

En esta página
Enterate del próximo post
Un mail cuando publico algo nuevo. Sin spam y te podés dar de baja cuando quieras.

Un mail cuando publico algo nuevo. Sin spam y te podés dar de baja cuando quieras.
El post de valor y referencia estableció que los primitivos se comparan por valor. Faltó la otra mitad de esa idea: qué hace JavaScript exactamente cuando compara dos valores, y por qué == y === pueden dar resultados distintos con los mismos dos operandos.
0 == "0"; // true
null == undefined; // true
"" == false; // true== se llama igualdad débil porque, si los dos operandos no son del mismo tipo, primero los convierte a un tipo común y recién ahí compara. 0 == "0" convierte el string "0" a número antes de comparar, y 0 === 0 es cierto. "" == false convierte los dos operandos a número ("" a 0, false a 0) y compara esos números. null == undefined es un caso aparte: la especificación los declara iguales entre sí por regla propia, sin conversión de por medio, y distintos de cualquier otro valor.
0 === "0"; // false
null === undefined; // false
"" === false; // false=== compara tipo y valor a la vez, sin ningún paso de conversión antes. Los mismos tres pares de doble-igual.js, comparados con ===, dan los tres false: 0 y "0" no son del mismo tipo, null y undefined tampoco, y "" y false tampoco. Ninguna conversión implícita interviene, así que el resultado depende únicamente de lo que los dos operandos ya eran antes de la comparación.
NaN == NaN; // false
NaN === NaN; // false
[] == false; // true
[] == ""; // trueNaN no es igual a sí mismo, con ninguno de los dos operadores: es el único valor de JavaScript para el que x == x puede dar false. [] == false sorprende más: un array se convierte primero a string ([] se convierte a ""), y esa string vacía se convierte después a número (0), el mismo camino que ya recorrió "" en el ejemplo anterior. [] == "" confirma el paso intermedio: la comparación se resuelve ahí, antes de necesitar el segundo paso a número.
typeof 42; // "number"
typeof "hola"; // "string"
typeof undefined; // "undefined"
typeof (() => {}); // "function"
typeof {}; // "object"typeof devuelve una string con el nombre del tipo del valor que recibe. Funciona para distinguir la mayoría de los casos: números, strings, undefined, funciones, objetos.
typeof null; // "object"
null === undefined; // false
typeof null === typeof {}; // truetypeof null devuelve "object", no "null". Es un error de la primera versión del lenguaje que nunca se corrigió, porque corregirlo hoy rompería una enorme cantidad de código existente que depende de ese comportamiento. La consecuencia práctica es que typeof solo no alcanza para distinguir null de un objeto real: hace falta compararlo aparte, como ya se vio arriba con ===.
==conviene evitarlo salvo para el caso puntual denull == undefined, que es además la única forma directa de preguntar "¿esto esnulloundefined?" en una sola comparación.===es la opción por defecto para todo lo demás, porque no depende de memorizar qué conversión aplica a cada combinación de tipos. Ytypeofidentifica casi cualquier tipo correctamente, con la única excepción histórica denull.
El próximo post retoma la cadena de prototipos desde otro ángulo: cómo fijar el prototipo de un objeto a mano, con Object.create, sin pasar por ningún constructor.