This site runs best with JavaScript enabled.

JavaScript default parameters

June 25, 2018

Video Blogger

Photo by Jude Beck on Unsplash


The expressive power of expressions in default values for parameters

Today I thought I'd take you through one of the examples from my es6 workshop.

Consider the following code:

1function getCandy(kind, size, upperKind, callback) {
2 if (!kind) {
3 requiredParam('kind')
4 }
5 if (!size) {
6 requiredParam('size')
7 }
8 upperKind = upperKind || kind.toUpperCase()
9 callback = callback || function noop() {}
10
11 const result = {kind, size, upperKind}
12 callback(result)
13 return result
14}
15
16function requiredParam(argName) {
17 throw new Error(`${argName} is required`)
18}

It's fairly simple, but there are potential bugs (read about Falsy on MDN) and some annoying boilerplate. Luckily for us, ES6 introduced new syntax into JavaScript that we can use to simplify things a bit. In particular: default parameters. Let's checkout what the above would be like when using this feature.

1function getCandy(
2 kind = requiredParam('kind'),
3 size = requiredParam('size'),
4 upperKind = kind.toUpperCase(),
5 callback = function noop() {},
6) {
7 const result = {kind, size, upperKind}
8 callback(result)
9 return result
10}
11
12function requiredParam(argName) {
13 throw new Error(`${argName} is required`)
14}

Notice that we're able to take each expression and put it on the right side of the equals sign. If the parameter is undefinedthen the expression on the right side will be evaluated. This allows us to only call the requiredParam function if kind or size is undefined. It also is possible to use the value of other parameters in our expression like we do in the default param for upperKind which I find to be a ridiculously cool feature and I use this all the time in options configuration for some of my tools (for example).

I'll add that the same kinds of semantics would apply for object destructuring (whether as a parameter or not) as well. For example, if we change the arguments to be an options object:

1function getCandy(options = {}) {
2 const {
3 kind = requiredParam('kind'),
4 size = requiredParam('size'),
5 upperKind = kind.toUpperCase(),
6 callback = function noop() {},
7 } = options
8 // etc...
9}

Or, if we want to destructure the options object directly in the parameter list:

1function getCandy({
2 kind = requiredParam('kind'),
3 size = requiredParam('size'),
4 upperKind = kind.toUpperCase(),
5 callback = function noop() {},
6} = {}) {
7 // etc...
8}

Fun stuff!

Conclusion

I hope you find this helpful! If you'd like to watch me talk about this a bit, you can check out this section of my ES6 workshop I gave and recorded at PayPal a while back: ES6 and Beyond Workshop Part 1 at PayPal (Jan 2017). Good luck!

Learn more about JavaScript from me:

Also, don't forget to subscribe to my youtube channel for my daily devtips, like the one today where I demo some advanced features of destructuring!

Things to not miss:

  • Semver Calc — A sweet new app by Tarang Hirani and Shriram Balaji. It allows you to try out semver ranges on packages versions to fine-tune the version range. Especially useful for peerDependencies.
  • AnxietyTech — A conference on July 18th, 2018 to bring awareness of mental health issues in tech. Use code TECH for \$25 off.
  • Refined Twitter — Browser extension that simplifies the Twitter interface and adds useful features. I love it.

Discuss on TwitterEdit post on GitHub

Share article
loading relevant upcoming workshops...
Kent C. Dodds

Kent C. Dodds is a JavaScript software engineer and teacher. He's taught hundreds of thousands of people how to make the world a better place with quality software development tools and practices. He lives with his wife and four kids in Utah.