Truthy y Falsy en JavaScript

Truthy y Falsy en JavaScript

2 minutos de lectura

Debido a la coerción en JavaScript cuando una expresión se evalúa como booleano (un if, la condición de un while, una ternaria, etc) el lenguaje convertirá el valor en true o false. Hay casos concretos que darán false:

0  // cero
-0 // cero negativo
0n // cero de tipo BigInt
"" // cadena de text vacía
'' // cadena de text vacía
`` // cadena de text vacía
null
undefined
NaN

Cualquier otro valor al ser evaluado como booleano devolverá true.

Ejemplos de falsy y truthy values
>
0 ? 'Soy truthy' : 'Soy falsy'
"Soy falsy"
>
-42 ? 'Soy truthy' : 'Soy falsy'
"Soy truthy"
>

En JavaScript existe la coerción, que se trata de una conversión de tipos cuando se va a evaluar una variable. Por ejemplo, si vamos a comparar entre un número y una cadena de texto:

Ejemplos de coerción
>
'1' == 1
true
>
'1' === 1
false
>

Como vemos en el primer caso nos devuelve true y en el segundo false. La diferencia entre == y === es que == hace una coerción de tipos a la hora de comparar. Lo mismo pasa en casos negativos:

Ejemplos de coerción
>
'1' != 1
false
>
'1' !== 1
true
>

En estos ejemplos cuando comparamos números y cadenas de texto, pero, ¿qué pasa si evaluamos variables como si fueran booleanos?

Coerción de booleanos
>
0 ? 'Soy truthy' : 'Soy falsy'
"Soy falsy"
>
-42 ? 'Soy truthy' : 'Soy falsy'
"Soy truthy"
>

Lo que pasa es que JavaScript trata de convertir la variable a booleano, ya que estás evaluándola como una condición. En la práctica es lo mismo que tratar de hacer Boolean(0):

Convirtiendo a booleano
>
Boolean(0)
false
>
Boolean(-42)
true
>

Por eso en JavaScript se habla de valores truthy y falsy, que no son true o false, pero si son evaluados como booleanos se comportan como tales. Esto puede conllevar a problemas, ya que un valor es truthy o falsy dependiendo de cómo está siendo evaluado:

Un valor puede ser falsy dependiendo de cómo sea evaluado
>
const zeroNumber = 1 - 1
0
>
zeroNumber + 1
1
>
Boolean(zeroNumber)
false
>
const zeroString = String(zeroNumber)
"0"
>
Boolean(zeroString)
true
>

La parte positiva es que los valores que pueden ser falsy son limitados:

0  // cero
-0 // cero negativo
0n // cero de tipo BigInt
"" // cadena de text vacía
'' // cadena de text vacía
`` // cadena de text vacía
null
undefined
NaN

Por otro lado, todo valor que no es falsy es truthy:

Valores truthy
>
Boolean(1)
true
>
Boolean('En un lugar de la Mancha...')
true
>
Boolean({})
true
>
Boolean([])
true
>
Boolean(class Test {})
true
>
Boolean(() => {})
true
>

Saber esto te ayudará a mejorar la forma en la que construyes tus condicionales en JavaScript. Por ejemplo, imagina que te han pedido que para un usuario de la plataforma en la que estás trabajando muestre un mensaje con su saldo. En caso de que el usuario no tenga saldo, que no que sea 0, significa que todavía no ha activado su cuenta por lo que debería mostrar un mensaje notificándolo. Teniendo todo esto en cuenta hemos hecho esta función:

function parseBalance({name, balance}) {
  if (balance) {
    return `El saldo de ${name} es ${balance.toFixed(2)} €.`
  } else {
    return `La cuenta de ${name} no ha sido activada.`
  }
}

Ahora vamos a probar con diferentes combinaciones para ver si podemos tener algún resultado inesperado:

Mostrar saldo del usuario
>
parseBalance({name: 'Carlos', balance: 120})
"El saldo de Carlos es 120.00 €."
>
parseBalance({name: 'Juan'})
"La cuenta de Juan no ha sido activada."
>
parseBalance({name: 'Pepe', balance: 0})
"La cuenta de Pepe no ha sido activada."
>

Uy, parece ser que en el caso de Pepe ha pasado algo que no debería. Según lo que nos han dicho Pepe debería tener la cuenta activada, ya que nos han pasado el saldo de su cuenta. Lo que pasa es que su saldo es 0, lo cual al pasar por nuestro if se evalúa como false. Arreglar esto es fácil, sólo tenemos que comprobar que el saldo no sea undefined:

function parseBalance({name, balance}) {
  if (balance !== undefined) {
    return `El saldo de ${name} es ${balance.toFixed(2)} €.`
  } else {
    return `La cuenta de ${name} no ha sido activada.`
  }
}
Mostrar saldo del usuario
>
parseBalance({name: 'Carlos', balance: 120})
"El saldo de Carlos es 120.00 €."
>
parseBalance({name: 'Juan'})
"La cuenta de Juan no ha sido activada."
>
parseBalance({name: 'Pepe', balance: 0})
"El saldo de Pepe es 0.00 €."
>

Ahora sí funciona como nos ha pedido. Es un ejemplo muy básico, pero creo que refleja bien el problema de no controlar los valores falsy. Resumiéndolo: el problema es que a veces un falsy value puede ser un valor válido en el dominio de nuestra aplicación, llevando a errores inesperados. Si el caso de Pepe hubiera sido real habría intentado una y otra vez activar su cuenta, contactado con Atención al Cliente o dejado de usar la aplicación directamente.

Espero que esto te haya ayudado a que partir de ahora le des una vuelta de más cuando tengas que escribir un condicional en JavaScript 😉.

author
author

Hola! Soy Ulises Santana

Full Stack Developer con JavaScript como lengua materna y la web como patria. Trasteando con tecnologías desde las Islas Canarias 🏝️

  • Twitter
    https://twitter.com/ulisesantana
  • Github
    https://github.com/ulisesantana
  • Curriculum Vitae
    /cv
Comparte este artículo:

Artículos relacionados

  • Twitter
    https://twitter.com/ulisesantana
  • Github
    https://github.com/ulisesantana
  • Curriculum Vitae
    /cv

Copyright © 2022