Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using destructuring to define optional parameters in ES6

I have a function that performs an AJAX call, as such:

let retrieveData = (section, sectionItem, callback) => {
    ...
}

Where the second parameter is optional, i.e. in some cases that parameter is required, in others it isn't:

let data = retrieveData(aSection, aSectionItem, function(json)) {
    ...
});

and:

let data = retrieveData(aSection, undefined, function(json)) {
    ...
});

In the second instance I'd like to be able to omit the undefined parameter and I believe assigning options/defaults by way of destructuring is the answer (as per this example: https://javascript.info/destructuring-assignment#smart-function-parameters), but I'm coming up short on how to structure the code.

like image 713
Ryan Avatar asked Sep 29 '17 07:09

Ryan


2 Answers

You current way :

let retrieveData = (section, sectionItem, callback) => {
  console.log('Section :', section);
  console.log('Section item :', sectionItem);
  console.log('Callback :', callback);
}

retrieveData('a', 'b', () => {});
retrieveData('a', undefined, () => {});

ES6 solutions

  1. With ES6 you can pass parameters as an object like following code. Note that if sectionItem is omitted, it'll be undefined.

let retrieveData = ({ section, sectionItem, callback }) => {
  console.log('Section :', section);
  console.log('Section item :', sectionItem);
  console.log('Callback :', callback);
}

retrieveData({
  section: 'a',
  sectionItem: 'b',
  callback: () => {}
});
retrieveData({
  section: 'a',
  callback: () => {}
});

  1. You can also set a default value to sectionItem :

let retrieveData = ({ section, sectionItem = 'defaultValue', callback }) => {
  console.log('Section :', section);
  console.log('Section item :', sectionItem);
  console.log('Callback :', callback);
}

retrieveData({
  section: 'a',
  sectionItem: 'b',
  callback: () => {}
});
retrieveData({
  section: 'a',
  callback: () => {}
});

ES5 Solutions

  1. As stated in the comments, you could also simply move sectionItem to the end of the function, making it easier to omit.

let retrieveData = (section, callback, sectionItem) => {
    console.log('Section :', section);
    console.log('Section item :', sectionItem);
    console.log('Callback :', callback);
}

retrieveData('a', () => {}, 'b');
retrieveData('a', () => {}); // Here you omit the parameter
  1. Or, if you need to be ES5 compliant, you can reproduce ES6 behavior by doing something like this. But it's less clearer without documentation since we don't know exactly which parameters the function is expecting.

let retrieveData = (options) => {
    console.log('Section :', options.section);
    console.log('Section item :', options.sectionItem);
    console.log('Callback :', options.callback);
}

retrieveData({
  section: 'a', 
  sectionItem: 'b',
  callback: () => {}
});
retrieveData({
  section: 'a', 
  callback: () => {}
});
like image 60
Serge K. Avatar answered Sep 21 '22 02:09

Serge K.


Please use optional arguments and deconstruct your parameters.

const foo = (section, {sectionItem, callback} = {}) => {
  console.log(section, sectionItem, callback);
}

So both sectionItem and callback are optional:

let data = retrieveData(aSection, {
  sectionItem: 'some',
  callback: json => {
    ...
  },
});

This way you can call either of:

  • retrieveData(aSection)
  • retrieveData(aSection, {sectionItem: 'some'})
  • retrieveData(aSection, {callback: json => { ... }})

Another important aspect is you keep optional arguments verbose right from the caller.

like image 30
Adit Saxena Avatar answered Sep 18 '22 02:09

Adit Saxena