
Uso de parámetros predeterminados en ES6
Recientemente comencé a investigar más sobre las novedades de JavaScript, poniéndome al día con muchas de las nuevas características y mejoras de sintaxis que se han incluido en ES6 (es decir, ES2015 y posteriores).
Probablemente hayas oído hablar de las cosas habituales y hayas comenzado a utilizarlas: funciones de flecha, operadores let y const, descanso y dispersión, etc. Sin embargo, una característica que me llamó la atención es el uso de parámetros predeterminados en funciones , que ahora es una característica oficial de ES6+. Esta es la capacidad de hacer que sus funciones iniciales tengan parámetros con valores predeterminados incluso si la llamada a la función no los incluye.
La característica en sí es bastante sencilla en su forma más simple, pero hay bastantes sutilezas y errores que querrás tener en cuenta, que intentaré aclarar en esta publicación con algunos ejemplos de código y demostraciones.
Parámetros predeterminados en ES5 y versiones anteriores
Una función que proporciona automáticamente valores predeterminados para parámetros no declarados puede ser una protección beneficiosa para sus programas, y esto no es nada nuevo.
Antes de ES6, es posible que hayas visto o usado un patrón como este:
function getInfo (name, year, color) { year = (typeof year !== 'undefined') ? year : 2018; color = (typeof color !== 'undefined') ? color : 'Blue'; // remainder of the function...}
En este caso, la getInfo()
función tiene solo un parámetro obligatorio: name
. Los parámetros year
son color
opcionales, por lo que si no se proporcionan como argumentos cuando getInfo()
se llama a , se les asignarán valores predeterminados:
getInfo('Chevy', 1957, 'Green');getInfo('Benz', 1965); // default for color is "Blue"getInfo('Honda'); // defaults are 2018 and "Blue"
Pruébelo en CodePen
Sin este tipo de control y protección, cualquier parámetro no iniciado tendría por defecto un valor de undefined
, lo que normalmente no es deseable.
También puedes usar un patrón verdadero/falso para verificar parámetros que no tienen valores:
function getInfo (name, year, color) { year = year || 2018; color = color || 'Blue'; // remainder of the function...}
Pero esto puede causar problemas en algunos casos. En el ejemplo anterior, si pasa un valor de 0
para el año, el valor predeterminado 2018 lo anulará porque 0
se evalúa como falso. En este ejemplo específico, es poco probable que le preocupe eso, pero hay muchos casos en los que su aplicación podría querer aceptar un valor de 0 como un número válido en lugar de un valor falso.
Pruébelo en CodePen
Por supuesto, incluso con el typeof
patrón, es posible que tengas que hacer más comprobaciones para tener una solución verdaderamente a prueba de balas. Por ejemplo, es posible que espere una función de devolución de llamada opcional como parámetro. En ese caso, compararlo undefined
solo no sería suficiente. También deberías comprobar si el valor pasado es una función válida.
Esto es un pequeño resumen que cubre cómo manejamos los parámetros predeterminados antes de ES6. Vemos una manera mucho mejor.
Parámetros predeterminados en ES6
Si su aplicación requiere que utilice funciones anteriores a ES6 por motivos heredados o debido a la compatibilidad del navegador, es posible que deba hacer algo similar a lo que describí anteriormente. Pero ES6 lo ha hecho mucho más fácil. A continuación se explica cómo definir valores de parámetros predeterminados en ES6 y más allá:
function getInfo (name, year = 2018, color = 'blue') { // function body here...}
Pruébelo en CodePen
Es así de simple.
Si se pasan valores year
y color
a la llamada de función, los valores pasados como argumentos reemplazarán a los definidos como parámetros en la definición de la función. Esto funciona exactamente de la misma manera que con los patrones de ES5, pero sin ese código adicional. Mucho más fácil de mantener y mucho más fácil de leer.
Esta característica se puede utilizar para cualquiera de los parámetros en el encabezado de la función, por lo que podría establecer un valor predeterminado para el primer parámetro junto con otros dos valores esperados que no tienen valores predeterminados:
function getInfo (name = 'Pat', year, color) { // function body here...}
Lidiar con los valores omitidos
Tenga en cuenta que, en un caso como el anterior, si desea omitir el name
argumento opcional (y, por lo tanto, usar el valor predeterminado) mientras incluye un year
and color
, deberá pasarlo undefined
como marcador de posición para el primer argumento:
getInfo(undefined, 1995, 'Orange');
Si no hace esto, lógicamente siempre se asumirá que el primer valor es name
.
Lo mismo se aplicaría si quisieras omitir el year
argumento (el segundo) e incluir los otros dos (asumiendo, por supuesto, que el segundo parámetro es opcional):
getInfo('Charlie', undefined, 'Pink');
También debes tener en cuenta que lo siguiente puede producir resultados inesperados:
function getInfo (name, year = 1965, color = 'blue') { console.log(year); // null}getInfo('Frankie', null, 'Purple');
Pruébelo en CodePen
En este caso, pasé el segundo argumento como null
, lo que podría llevar a algunos a creer que el year
valor dentro de la función debería ser 1965
, que es el valor predeterminado. Pero esto no sucede porque null
se considera un valor válido. Y esto tiene sentido porque, según la especificación, null
el motor JavaScript lo ve como la ausencia intencional del valor de un objeto, mientras que undefined
se ve como algo que sucede incidentalmente (por ejemplo, cuando una función no tiene un valor de retorno, devuelve undefined
). .
Así que asegúrese de usarlo undefined
y no null
cuando desee que se use el valor predeterminado. Por supuesto, puede haber casos en los que desee utilizar null
y luego tratar el null
valor dentro del cuerpo de la función, pero debe estar familiarizado con esta distinción.
Valores de parámetros predeterminados y el argumentsobjeto
Otro punto que vale la pena mencionar aquí es el relacionado con el arguments
objeto. El arguments
objeto es un objeto similar a una matriz, accesible dentro del cuerpo de una función, que representa los argumentos pasados a una función.
De modo no estricto, el arguments
objeto refleja cualquier cambio realizado en los valores de los argumentos dentro del cuerpo de la función. Por ejemplo:
function getInfo (name, year, color) { console.log(arguments); /* [object Arguments] { 0: "Frankie", 1: 1987, 2: "Red" } */ name = 'Jimmie'; year = 1995; color = 'Orange'; console.log(arguments); /* [object Arguments] { 0: "Jimmie", 1: 1995, 2: "Orange" } */}getInfo('Frankie', 1987, 'Red');
Pruébelo en CodePen
Observe que, en el ejemplo anterior, si cambian los valores de los parámetros de la función, esos cambios se reflejan en el arguments
objeto. Esta característica se demostró más problemática que beneficiosa, por lo que en el modo estricto el comportamiento es diferente:
function getInfo (name, year, color) { 'use strict'; name = 'Jimmie'; year = 1995; color = 'Orange'; console.log(arguments); /* [object Arguments] { 0: "Frankie", 1: 1987, 2: "Red" } */} getInfo('Frankie', 1987, 'Red');
Pruébelo en CodePen
Como se muestra en la demostración, en modo estricto el arguments
objeto conserva sus valores originales para los parámetros.
Eso nos lleva al uso de parámetros predeterminados. ¿Cómo se comporta el arguments
objeto cuando se utiliza la función de parámetros predeterminados? Echa un vistazo al siguiente código:
function getInfo (name, year = 1992, color = 'Blue') { console.log(arguments.length); // 1 console.log(year, color); // 1992 // "Blue" year = 1995; color = 'Orange'; console.log(arguments.length); // Still 1 console.log(arguments); /* [object Arguments] { 0: "Frankie" } */ console.log(year, color); // 1995 // "Orange"}getInfo('Frankie');
Pruébelo en CodePen
Hay algunas cosas a tener en cuenta en este ejemplo.
Primero, la inclusión de parámetros predeterminados no cambia el arguments
objeto. Entonces, como en este caso, si paso solo un argumento en la llamada funcional, el arguments
objeto contendrá un solo elemento, incluso con los parámetros predeterminados presentes para los argumentos opcionales.
En segundo lugar, cuando los parámetros predeterminados están presentes, el arguments
objeto siempre se comportará de la misma manera en modo estricto y en modo no estricto. El ejemplo anterior está en modo no estricto, que generalmente permite arguments
modificar el objeto. Pero esto no sucede. Como puede ver, la longitud de arguments
sigue siendo la misma después de modificar los valores. Además, cuando se registra el objeto en sí, el name
valor es el único presente.
Expresiones como parámetros predeterminados
La función de parámetros predeterminados no se limita a valores estáticos, sino que puede incluir una expresión que se evaluará para determinar el valor predeterminado. A continuación se muestra un ejemplo para demostrar algunas cosas que son posibles:
function getAmount() { return 100;}function getInfo (name, amount = getAmount(), color = name) { console.log(name, amount, color)}getInfo('Scarlet');// "Scarlet"// 100// "Scarlet"getInfo('Scarlet', 200);// "Scarlet"// 200// "Scarlet"getInfo('Scarlet', 200, 'Pink');// "Scarlet"// 200// "Pink"
Pruébelo en CodePen
Hay algunas cosas a tener en cuenta en el código anterior. Primero, estoy permitiendo que el segundo parámetro, cuando no está incluido en la llamada a la función, sea evaluado por medio de la getAmount()
función. Esta función se llamará solo si no se pasa un segundo argumento. Esto es evidente en la segunda getInfo()
llamada y el registro posterior.
El siguiente punto clave es que puedo usar un parámetro anterior como predeterminado para otro parámetro. No estoy del todo seguro de qué tan útil sería esto, pero es bueno saber que es posible. Como se puede ver en el código anterior, la getInfo()
función establece el tercer parámetro ( color
) para que sea igual al valor del primer parámetro ( name
), si el tercer parámetro no está incluido.
Y, por supuesto, dado que es posible utilizar funciones para determinar los parámetros predeterminados, también puede pasar un parámetro existente a una función utilizada como parámetro posterior, como en el siguiente ejemplo:
function getFullPrice(price) { return (price * 1.13);}function getValue (price, pricePlusTax = getFullPrice(price)) { console.log(price.toFixed(2), pricePlusTax.toFixed(2))}getValue(25);// "25.00"// "28.25"getValue(25, 30);// "25.00"// "30.00"
Pruébelo en CodePen
En el ejemplo anterior, estoy haciendo un cálculo de impuestos rudimentario en la getFullPrice()
función. Cuando se llama a esta función, utiliza el price
parámetro existente como parte de la pricePlusTax
evaluación. Como se mencionó anteriormente, la getFullPrice()
función no se llama si se pasa un segundo argumento getValue()
(como se demostró en la segunda getValue()
llamada).
Dos cosas a tener en cuenta respecto a lo anterior. Primero, la llamada a la función en la expresión del parámetro predeterminado debe incluir paréntesis; de lo contrario, recibirá una referencia a la función en lugar de una evaluación de la llamada a la función.
En segundo lugar, solo puede hacer referencia a parámetros anteriores con parámetros predeterminados. En otras palabras, no puedes hacer referencia al segundo parámetro como argumento en una función para determinar el valor predeterminado del primer parámetro:
// this won't workfunction getValue (pricePlusTax = getFullPrice(price), price) { console.log(price.toFixed(2), pricePlusTax.toFixed(2))}getValue(25); // throws an error
Pruébelo en CodePen
De manera similar, como era de esperar, no puede acceder a una variable definida dentro del cuerpo de la función desde un parámetro de función.
Conclusión
Esto debería cubrir casi todo lo que necesita saber para aprovechar al máximo el uso de parámetros predeterminados en sus funciones en ES6 y superiores. La función en sí es bastante fácil de usar en su forma más simple pero, como comenta aquí, hay bastantes detalles que vale la pena comprender.
Si deseas leer más sobre este tema, aquí hay algunas fuentes:
- Comprensión de ECMAScript 6 por Nicholas Zakas. Esta fue mi fuente principal para este artículo. Nicolás es definitivamente mi autor de JavaScript favorito.
- Objeto de argumentos en MDN
- Parámetros predeterminados en MDN
Deja una respuesta