La coerción en Javascript se refiere al comportamiento de cambiar un tipo de dato por otro. Todo en Javascript ya sea un objeto o un valor primitivo puede ser sujeto de coerción.
Hay 3 tipos de coerción que pueden hacerse:
String
Numeric
Boolean
También es importante que sepas que una coerción puede ser explícita o implícita. Obviamente la que no siempre es del todo clara es precisamente la coerción implícta, ya que Javascript decide cuando realizarla, y es en la que nos enfocaremos en este artículo.
Pero antes de empezar y para que entiendas todo perfectamente, un recordatorio:
Los valores primitivos de Javascript
Null
Undefined
Boolean
Number
BigInt
String
Symbol
Ahora si. Empieza lo bueno.
Coerción a String
Esta es la coerción implícita más simple y común de las 3. Curiosamente es la que única se usa con total intención incluso por programadores novicios. La razón es simple, esta coerción es la que permite el comportamiento que conocemos como concatenación.
Escenarios de Ocurrencia
Se activa siempre que haya un operador + y un String.
Ejemplos:
const s1 = 58 + '58'; // 5858
const s2 = true + '3'; // true3
const s3 = {arr: []} + ' hola'; // [object Object] hola
const s4 = null + ''; // null
const s5 = undefined + ' in js'; // undefined in js
*Puedes ver que en el caso de un objeto, a pesar de haber sido convertido a String, el resultado no es legible. Este es el comportamiento esperado cuando hablamos de coerción a String de objetos.
Al hacer la coerción implicta JS convierte el valor primitivo u objeto en un String y procede a hacer la operación de concatenación.
Coerción a Number
La conversión numérica puede parecer mas compleja de entender dado que se activa en muchos mas casos.
Escenarios de Ocurrencia
- Operador de igualdad (no estricta)
- ==
- !=
- Operadores de comparación
- >
- <
- <=
- >=
- Operadores aritméticos
- –
- + (siempre y cuando no haya un String)
- *
- /
- %
- Operador unario
- +
- Operadores bitwise
- |
- &
- ^
- ~
Tabla de conversión
Casos especiales que no son obvios a primera vista:
Valores primitivos u objetos | Valor convertido a Number |
“” | 0 |
“\n” | 0 |
“a String” | NaN |
null | 0 |
undefined | NaN |
true | 1 |
false | 0 |
*Si gustas verificar los valores tu mismo puedes verificar la conversión que hace JS de un valor mediante una conversión explícita.
Ejemplo:
Number(true); // 1
Number(false); // 0
Ejemplos:
Igualdad no estricta
const n1 = '10' == 10; // true
const n2 = '0' != 0; // false
const n3 = 'hello' == NaN; // false
Si te fijas notarás algo raro con n3
. Teóricamente un String cualquiera debería ser convertido a el valor NaN
. Sin embargo, el valor de n3
regresa false
a la hora de compararlo…¿Por qué?
Bueno de hecho Javascript tiene un comportamiento especial con NaN
. NaN
es un valor especial que representa un valor que debería haber resultado en un número pero no lo fue. De ahís sus siglas: “Not a Number”.
El hecho de que este sea un valor especial, causa comportamientos como el que sigue:
const nanEqualsNan = NaN == NaN; // false
Por lo que si bien el valor si se convierte a NaN
, JS igual regresa false.
A pesar de esto si hay una forma de verificar que un valor es NaN
:
const n3 = isNaN('hello'); // true
Comparación
const n4 = -4 > '-2'; // false
const n5 = ' -100 ' <= 50; // true
Aritméticos
const n6 = '23' - 12; // 11
const n7 = 35 * '100'; // 3500
const n8 = 71 / 'blablabla'; // NaN
*Recuerda que si cambiarás cualquiera de los operadores anteriores (-, *, /) por el operador de suma (+), entonces JS haría una conversión a Strin gen lugar de a Number.
const s1 = '23' + 12; // 2312
const s2 = 35 + '100'; // 3500
const s3 = 71 + 'blablabla'; // 71blablabla
Unario
const n9 = +'1234'; // 1234
*En este caso no se hace una conversión a String porque el propóstio de esa conversión es concatenar algo. Como no hay nada que concatenar JS opta por la conversión a Number.
Bitwise
const n10 = '66' | 11; // 75
const n11 = 101 & '100'; // 100
Casos Especiales
En estos ejemplos puedes ver como funcionan la coerción del string de salto de línea y de los booleanos.
const n12 = 0 == '\n'; // true
const n13 = 1 == true; // true
const n14 = 0 == false; // true
const n15 = 1 - '\n'; // 1
const n16 = 1 - true; // 0
const n17 = 1 - false; // 1
Finalmente podemos ver el comportamiento especial de null
y NaN
.
const n18 = 0 == null; // false
const n19 = 1 - null; // 1
*JS tiene comportamientos especiales con null
. Lo convierte 0 en operaciones aritméticas, pero en comparaciones siempre dará false
.
Coerción a Boolean
Escenarios de Ocurrencia
- Operadores lógicos
- ||
- &&
- !
- Contextos lógicos
- if ( … )
- while ( … )
Tabla de conversión
Casos especiales que vale la pena memorizar.
Valores primitivos u objetos | Valor convertido a Boolean |
“” | false |
0 | false |
NaN | false |
null | false |
undefined | false |
{} | true |
[] | true |
function() {} | true |
Los valores que se convierten a false
durante una coerción implícita son denominados como valores falsy. Los valores que se convierten a true
durante el mismo proceso se denominan como valores truthy.
*truthy y falsy no son palabras reales. La traducción mas directa sería algo como, verdaderoso y falsoso respectivamente.
*No olvides que si gustas verificar los valores tu mismo puedes verificar la conversión que hace JS de un valor mediante una conversión explícita.
Ejemplo:
Boolean(null); // false
Boolean([]); // true
Ejemplos:
Truthy
const b1 = {} && true; // true
const b2 = [] || false; // []
const b3 = !function() {}; // false
Falsy
const b4 = "" || false; // false
const b5 = 0 || false; // false
const b6 = !NaN; // true
const b7 = !null; // true
if (undefined) {
// Unreachable code
} else {
// undefined was false
}
Las reglas de coerción implícita son la fuente de mucha confusión y frustración cuando se usa JS. Lamentablemente Javascript no es perfecto y tiene muchas cosas que podrían ser mejor. Sin embargo entender estas reglas y escenarios te ayudará a debuggear mejor tu código y evitar tener problemas con los tipos de datos.