When writing modern JavaScript, it's common to collect multiple optional parameters into a trailing "options" object. This allows clients to pass a subset of options and gives context to arguments at the call site. It also permits the API to use ES6 default parameters. But it can be tricky to get default parameters right with objects. Here's how.
Options objects
Once upon a time, if you wanted to dispatch a mouse event, you had to call an API that looked like this:
|
There were sensible defaults for every parameter except type
, but the API was not able to express this. Specifying a value for relatedTarget
meant specifying values for every other parameter, leading to insanely long, inscrutable function calls like:
|
This was fixed by collecting the optional parameters into a trailing object:
|
With this sort of API, the client can specify a subset of options. And as a bonus, the options are named at the call site, kind of like Python's named parameters:
|
Default parameters
Another downside of APIs like initMouseEvent
is that they can't effectively use ES6 default parameters. This is because parameters are set left-to-right, so multiple default parameters are rarely practical:
|
With an options object, you can write
|
However, this API does not express that x
and y
are independent options. Instead, it forces x
and y
to be passed together:
f(); // [1, 2]
f({ x: 1 }) // [1, undefined]
The problem is that options
is defined wholesale. The way to fix this is to use another ES6 feature, destructuring assignment, to describe the structure of options
. You'll no longer be able to reference options
per se, but it's often nicer to get "direct" access to each key, and then you can specify the defaults on a per-key basis:
|
But there's one final fix to be made. The previous version of the function has forced the client to pass an object:
The way to fix this is to default the options object to an empty object.
|
Conclusion
Default parameters are an awesome ES6 feature. However, the ability to specify objects as default values is a clear footgun. You should always specify default options by destructuring, while making sure that the options object is defined by defaulting to an empty object.
Working at the cutting edge of JavaScript development means getting used to some new syntax. If you'd like to join us, drop us a line at careers@mixmax.com.