Destructured Parameters
Destructuring has one more particularly helpful use case, and that is when passing function arguments. When a JavaScript function takes a large number of optional parameters, one common pattern is to create an options
object whose properties specify the additional parameters, like this:
// properties on options represent additional parameters
function setCookie(name, value, options) {
options = options || {};
let secure = options.secure,
path = options.path,
domain = options.domain,
expires = options.expires;
// code to set the cookie
}
// third argument maps to options
setCookie("type", "js", {
secure: true,
expires: 60000
});
Many JavaScript libraries contain setCookie()
functions that look similar to this one. In this function, the name
and value
arguments are required, but secure
, path
, domain
, and expires
are not. And since there is no priority order for the other data, it’s efficient to just have an options
object with named properties, rather than list extra named parameters. This approach works, but now you can’t tell what input the function expects just by looking at the function definition; you need to read the function body.
Destructured parameters offer an alternative that makes it clearer what arguments a function expects. A destructured parameter uses an object or array destructuring pattern in place of a named parameter. To see this in action, look at this rewritten version of the setCookie()
function from the last example:
function setCookie(name, value, { secure, path, domain, expires }) {
// code to set the cookie
}
setCookie("type", "js", {
secure: true,
expires: 60000
});
This function behaves similarly to the previous example, but now, the third argument uses destructuring to pull out the necessary data. The parameters outside the destructured parameter are clearly expected, and at the same time, it’s clear to someone using setCookie()
what options are available in terms of extra arguments. And of course, if the third argument is required, the values it should contain are crystal clear. The destructured parameters also act like regular parameters in that they are set to undefined
if they are not passed.
A>Destructured parameters have all of the capabilities of destructuring that you’ve learned so far in this chapter. You can use default values, mix object and array patterns, and use variable names that differ from the properties you’re reading from.
Destructured Parameters are Required
One quirk of using destructured parameters is that, by default, an error is thrown when they are not provided in a function call. For instance, this call to the setCookie()
function in the last example throws an error:
// Error!
setCookie("type", "js");
The third argument is missing, and so it evaluates to undefined
as expected. This causes an error because destructured parameters are really just a shorthand for destructured declaration. When the setCookie()
function is called, the JavaScript engine actually does this:
function setCookie(name, value, options) {
let { secure, path, domain, expires } = options;
// code to set the cookie
}
Since destructuring throws an error when the right side expression evaluates to null
or undefined
, the same is true when the third argument isn’t passed to the setCookie()
function.
If you want the destructured parameter to be required, then this behavior isn’t all that troubling. But if you want the destructured parameter to be optional, you can work around this behavior by providing a default value for the destructured parameter, like this:
function setCookie(name, value, { secure, path, domain, expires } = {}) {
// ...
}
This example provides a new object as the default value for the third parameter. Providing a default value for the destructured parameter means that the secure
, path
, domain
, and expires
will all be undefined
if the third argument to setCookie()
isn’t provided, and no error will be thrown.
Default Values for Destructured Parameters
You can specify destructured default values for destructured parameters just as you would in destructured assignment. Just add the equals sign after the parameter and specify the default value. For example:
function setCookie(name, value,
{
secure = false,
path = "/",
domain = "example.com",
expires = new Date(Date.now() + 360000000)
} = {}
) {
// ...
}
Each property in the destructured parameter has a default value in this code, so you can avoid checking to see if a given property has been included in order to use the correct value. Also, the entire destructured parameter has a default value of an empty object, making the parameter optional. This does make the function declaration look a bit more complicated than usual, but that’s a small price to pay for ensuring each argument has a usable value.