Menu

Parámetros por defecto en JavaScript: guía práctica

Cómo funcionan los parámetros en JavaScript: valores por defecto, cuándo se disparan con undefined, orden de evaluación y la diferencia entre parámetros y argumentos.

Parámetros vs argumentos

Dos términos que se confunden todo el tiempo. Un parámetro es el nombre que aparece en la definición de la función. Un argumento es el valor que le pasas al invocarla. Es la misma idea que en Python y en la mayoría de los lenguajes:

index.js
Output
Click Run to see the output here.

a y b son parámetros. 2 y 3 son argumentos. JavaScript los asocia por posición: el primer argumento va al primer parámetro, y así sucesivamente. La diferencia parece menor, pero es justo el vocabulario que usan los mensajes de error y la documentación de MDN.

JavaScript es flexible con la cantidad de argumentos

A diferencia de otros lenguajes, a JavaScript le da igual si pasas menos argumentos de los esperados o si te sobran. Los parámetros que falten toman el valor undefined, y los que sobren simplemente se ignoran sin avisar:

index.js
Output
Click Run to see the output here.

La primera llamada imprime Hello, Ada undefined: como last no recibió ningún valor, queda como undefined, y las template literals lo interpolan sin problema. Ni error ni advertencia. Esa permisividad a veces resulta cómoda y a veces es fuente de bugs, y justamente por eso existen los parámetros por defecto.

Cómo asignar un valor por defecto en JavaScript

Coloca = seguido del valor después del nombre del parámetro. Si quien llama a la función no pasa ese argumento (o pasa undefined), entra en juego el valor por defecto:

index.js
Output
Click Run to see the output here.

Las tres llamadas funcionan. La primera y la tercera disparan el valor por defecto, mientras que la segunda usa el valor que le pasamos. Esta sintaxis llegó con ES6: antes de 2015 había que escribir name = name || "friend" dentro del cuerpo de la función, con los bugs típicos que eso trae cuando entran valores falsy como 0 o "".

Los parámetros por defecto admiten cualquier expresión, no solo literales:

index.js
Output
Click Run to see the output here.

La expresión se evalúa en cada llamada, no una sola vez al definir la función. Así que aquí no hay ese problema de los valores por defecto mutables como en Python: cada llamada recibe un new Date() fresquito.

Solo undefined dispara el valor por defecto

Esta es la regla que pilla a mucha gente desprevenida. Los valores por defecto en JavaScript se activan cuando el argumento es undefined, no cuando es un valor falsy, y tampoco cuando es null:

index.js
Output
Click Run to see the output here.

Solo la última llamada usa "friend". Cuando pasas null de forma explícita, le estás diciendo a JavaScript "el valor es null", y él te toma la palabra. Lo mismo pasa con las cadenas vacías y los ceros: son valores reales, no argumentos ausentes.

Si quieres que null se comporte igual que un argumento faltante, tienes que encargarte tú a mano:

index.js
Output
Click Run to see the output here.

El operador ?? (coalescencia nula) considera que tanto null como undefined son "valores ausentes". Más adelante lo veremos a fondo en otro capítulo.

Parámetro por defecto basado en otro parámetro

Los parámetros se evalúan de izquierda a derecha, así que un valor por defecto puede apoyarse en cualquier parámetro declarado antes que él:

index.js
Output
Click Run to see the output here.

Una llamada con un único argumento produce un cubo. Con dos argumentos obtienes un prisma cuadrado. Y ojo con el orden: no puedes referenciar un parámetro que todavía no se ha declarado:

function bad(a = b, b = 1) {
  return a + b;
}

bad();   // ReferenceError: Cannot access 'b' before initialization

Las mismas reglas que con las variables declaradas con let: usarlas antes de declararlas es un error.

Los valores por defecto se llevan bien con la desestructuración

Puedes desestructurar parámetros y asignarles valores por defecto al mismo tiempo. Es un patrón muy habitual cuando la función recibe un "objeto de opciones" como argumento:

index.js
Output
Click Run to see the output here.

Aquí operan dos capas de valores por defecto. Los de dentro (role = "member", active = true) rellenan las propiedades que falten. El = {} de fuera cubre el caso de que quien llame a la función no pase ningún argumento — sin eso, createUser() intentaría desestructurar undefined y lanzaría un error.

El patrón parece denso al principio, pero aparece por todas partes en el JavaScript moderno. En cuanto tu ojo identifica { ... } = {} como "opciones con valores por defecto", se lee al vuelo.

Saltarse un argumento intermedio

JavaScript no tiene argumentos con nombre como Python. Para saltarte un parámetro intermedio y quedarte con su valor por defecto, tienes que pasar undefined de forma explícita:

index.js
Output
Click Run to see the output here.

Pasar undefined como prefix mantiene el valor por defecto. Queda feo. Si te descubres escribiendo undefined en las llamadas a menudo, es señal de que conviene pasar a un objeto de opciones:

index.js
Output
Click Run to see the output here.

Ahora quien invoca la función indica qué quiere sobrescribir, y el orden da igual.

Los valores por defecto no cuentan en length

Un detalle menor que casi nunca importa, pero que a veces confunde. La propiedad length de una función informa cuántos parámetros hay antes del primero que tiene un valor por defecto:

index.js
Output
Click Run to see the output here.

Algunas librerías que inspeccionan funciones (por ejemplo, ciertas herramientas de testing o de inyección de dependencias) usan length para contar los parámetros "obligatorios". Está bien saber que existe esta regla, pero no hace falta memorizarla a menos que estés desarrollando ese tipo de herramientas.

Lo que viene: rest y spread

Los valores por defecto sirven cuando ya conoces los parámetros de antemano. Pero a veces no es así: quieres que una función acepte cualquier cantidad de argumentos, o reenviar un conjunto de argumentos a otra función. Para eso están ...rest y el operador spread, que veremos a continuación.

Preguntas frecuentes

¿Cómo se define un valor por defecto para un parámetro en JavaScript?

Se añade = y el valor por defecto justo después del nombre del parámetro en la firma de la función: function greet(name = 'friend') { ... }. Si quien llama a la función no pasa nada (o pasa undefined de forma explícita), se usa el valor por defecto. Es sintaxis de ES6 y funciona en cualquier entorno moderno de JavaScript.

¿Qué diferencia hay entre parámetros y argumentos?

Los parámetros son los nombres que aparecen en la definición de la función: en function add(a, b), los parámetros son a y b. Los argumentos son los valores reales que pasas al invocarla: en add(2, 3), los argumentos son 2 y 3. Distinguirlos ayuda mucho cuando lees mensajes de error o documentación.

¿Se aplica el valor por defecto si paso null?

No. El valor por defecto solo se dispara cuando el argumento es undefined (o cuando directamente no se pasa). Al pasar null estás diciendo «te doy un valor, y ese valor es null», así que el default se ignora. Esto suele pillar por sorpresa a quien viene de lenguajes donde null y undefined son lo mismo.

¿Puede un valor por defecto depender de otro parámetro?

Sí. Los parámetros se evalúan de izquierda a derecha, así que un parámetro posterior puede apoyarse en los anteriores: function box(width, height = width). También puedes llamar a funciones en el default, por ejemplo function log(msg, time = Date.now()), y esa expresión se evalúa de nuevo en cada llamada.

Aprende a programar con Coddy

COMENZAR