Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Destructuring and re-structuring in function arguments?

I'm trying to use named function arguments and default values using destructuring.

function doSomething({arg1 = "foo", arg2 = "bar"} = {}) {
  console.log(arg1, arg2);
}

but I would also like to have access to the entire object, in case the user adds some extra fields. This doesn't actually work, but I'm shooting for something like this:

function doSomething(parameters = {arg1 = "foo", arg2 = "bar"} = {}) {
  console.log(arg1, arg2, parameters);   
  // parameters should contain arg1 and arg2, plus any additional user supplied keys.
}

Is there an elegant way to do this using destructuring? (I tried using arguments[0] but this doesn't actually include my default values for arg1, and arg2.)

Thanks.

like image 402
user3056556 Avatar asked Apr 04 '18 07:04

user3056556


1 Answers

You could do:

function doSomething({ arg1 = "foo", arg2 = "bar", ...otherParams } = {}) {
    console.log(arg1, arg2, otherParams);
}

...and then:

doSomething({ anotherParam: 'hello' });

...would log:

foo bar {anotherParam: "hello"}

This uses the spread operator, which you can play around with in the latest Chrome, and use in production apps that you are transpiling to ES5 with Babel. It's worth noting, however, that this adds more complex transpiled code while it is not supported in all browsers natively.

Also, from a code readability and architectural perspective, this function now has a lot of complexity with destructuring, default arguments, and the spread operator, so I would see if it is possible to simplify what you're doing to reduce the need to use all of these.

For example, if you were building a function to create a DOM element, you could write:

function createDOMElement(properties = {}) {
   // Could avoid `const` by doing destructuring in the function signature, but broke it onto another line for better readability.
   const {
    tagName = 'div',
    ...attributes
   } = properties;

   const anElement = document.createElement(tagName);
   Object.keys(attributes).forEach((key) => anElement.setAttribute(key, attributes[key]));
   return anElement;
}

...but you could just supply the tag name as a regular argument not a named argument and simplify it to:

function createDOMElement(tagName = 'div', attributes = {}) {
   const anElement = document.createElement(tagName);
   Object.keys(attributes).forEach((key) => anElement.setAttribute(key, attributes[key]));
   return anElement;
}
like image 118
Steve Harrison Avatar answered Sep 18 '22 14:09

Steve Harrison