Parámetros obligatorios y valores por defecto en funciones Javascript con ES6

28 Jun 2016

Introducción

Gracias a las nuevas características de ES6, Javascript puede manejar valores por defecto en nuestras funciones de forma nativa. Además, podemos forzar a nuestras funciones a devolver una excepción en caso de que un argumento requerido falte.

Ya había ido hablando de todo esto con anterioridad, pero creo que dada la importancia del tema, había que recogerlo todo de nuevo en un post actualizado.

¡Vamos a ello!

Valores por defecto al modo Vieja Escuela

Antes de ES6, podíamos definir los valores por defecto utilizando eso que llamamos evaluación perezosa por cortocircuito:

var myFunc = function ( param1, param2 ) {
    param1 || ( param1 = 'Hello' );
    param2 || ( param2 = 'World' );
 
    return param1 + ' ' + param2;
};
 
console.info( myFunc() ); // Hello World
console.info( myFunc( 'Goodbye', 'Lenin' ) ); // Goodbye Lenin

Valores por defecto al modo ES6

Con ES6, podemos indicar dichos valores directamente en la recogida de argumentos, tal y como haríamos en otros lenguajes como por ejemplo PHP:

var myFunc = function ( param1 = 'Hello', param2 = 'World' ) {
    return param1 + ' ' + param2;
};
 
console.info( myFunc() ); // Hello World
console.info( myFunc( undefined, undefined ) ); // Hello World
console.info( myFunc( 'Goodbye', 'Lenin' ) ); // Goodbye Lenin

IMPORTANTE: Hay que tener en cuenta que cuando pasamos el valor undefined, también estamos invocando al valor por defecto asignado.

Valores por defecto con sintaxis de Funciones Flecha

Si nos movemos a la sintaxis más moderna en declaración de funciones, las Funciones Flecha, no encontramos ningún problema al asignar valores por defecto:

var myFunc = ( param1 = 'Hello', param2 = 'World' ) => param1 + ' ' + param2;
 
console.info( myFunc( undefined ) ); // Hello World
console.info( myFunc( 'Goodbye', 'Lenin' ) ); // Goodbye Lenin

Ojo con el valor del objeto arguments

Cuando utilizamos los valores por defecto, tenemos que tener en cuenta que en caso de omisión, el objeto arguments no incorpora dicho valor por defecto:

var myFunc = function ( x = 10, y = 20, z = 30 ) {
    var sum = x + y + z;
 
    return sum + ' (' + arguments.length + ' arguments passed)';
};
 
console.info( myFunc( 1, 2, 3 ) ); // 6 (3 arguments passed)
console.info( myFunc( 1, 2 ) ); 33 (2 arguments passed)
console.info( myFunc( 1 ) ); 51 (1 arguments passed)

Sin embargo, sí que contaría como argumento el valor ‘undefined aunque éste dispare el valor por defecto:

console.info( myFunc( 1, 2, 3 ) ); // 6 (3 arguments passed)
console.info( myFunc( 1, 2, undefined ) ); // 33 (3 arguments passed)
console.info( myFunc( 1, undefined ) ); // 51 (2 arguments passed)

Ojo con los objetos literales (destructuración)

Si nuestra función va a recoger objetos como parámetros y queremos asignar un valor por defecto a sus claves, la sintaxis no es la que cabría esperar:

var myFunc = ( { x: 10, y: 10 } = {} ) => x * y;
 
console.info( myFunc() ); // Syntax error

El error de sintaxis se produce porque el intérprete está tratando de realizar una destructuración de los valores. Para que funcione correctamente, hay que asignarlos como si fueran variables tradicionales, con el signo ‘=’:

var myFunc = ( { x = 10, y = 10 } = {} ) => x * y;
 
console.info( myFunc( undefined ) ); // 100
console.info( myFunc( { x: 20 } ) ); // 200
console.info( myFunc( { x: 20, y: 20 } ) ); // 400

Exigiendo valores (o cómo indicar valores requeridos)

Si en lugar de pasar un valor al parámetro, invocamos una función, podemos crear un mecanismo que garantice un ‘valor requerido’:

var isRequired = function () {
    throw new Error( 'Missing parameter' );
};
 
var myFunc = function ( param1 = isRequired() ) {
    return param1;
};
 
console.info( myFunc( 'Hello World' ) );
console.info( myFunc() ); // Error: Missing parameter

Como cabe esperar, la sintaxis de tipo Funciones Flecha también funciona con este tipo de estructura:

var isRequired = () => { throw new Error( 'Missing parameter' ); };
 
var myFunc = ( param1 = isRequired() ) => param1;
 
console.info( myFunc( 'Hello World' ) );
console.info( myFunc() ); // Error: Missing parameter

Podríamos además aprovechar los argumentos de la función isRequired para añadir información sobre ese parámetro que falta:

var isRequired = function ( type ) {
    throw new Error( 'Missing parameter. Expected: ' + type );
};
 
var myFunc = function ( param1 = isRequired( 'string' ) ) {
    return param1;
};
 
console.info( myFunc( 'Hello World' ) );
console.info( myFunc() ); // Error: Missing parameter. Expected: string

Conclusión

Y estas serían varias de las funcionalidades que podemos implementar en nuestros códigos gracias a la nueva sintaxis de ES6. Se trata sin duda de una capa más a la hora de gestionar nuestros tipos que, de forma nativa, refuerzan la consistencia que tanto se ha echado en falta históricamente en Javascript.

Más:

Aún no tenemos debug!
Ningún marciano se ha comunicado.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *