9

I have several functions with optional callback:

let myFunc = (callback) => {
  callback = callback || (() => {});
  // do something...
  callback();
}

What is the best way to write the callback default parameter?

None of the following solutions satisfy me much:

1 If callback defined:

  if (typeof callback === 'function') {
    callback(); 
  }

Not compact at all!

2 Utility function:

let safeFunc = (callback) => {
  return callback || (() => {});
};

let myFunc = (callback) => {
  // do something...
  safeFunc(callback)();
}

but the problem is that in between this has changed, and it matters in my case.

3 Using call

let myFunc = (callback) => {
  // do something...
  safeFunc(callback).call(this);
}

Not very user friendly.

4 Creating ID function

const ID = () => {};

let myFunc = (callback=ID) => {
  // do something...
  callback();
}

Has external dependency, not very functionnal, though probably the best choice.

Community
  • 1
  • 1
Augustin Riedinger
  • 20,909
  • 29
  • 133
  • 206
  • There isn't necessarily a "best" way. 1 and 4 are good solutions, but note that they are not equivalent. If a value that is not a function is passed, 4 will throw and error, 1 won't. – Felix Kling Nov 30 '16 at 15:05
  • I can't see how this question is a duplicate of the referenced one. Also I don't understand why there are so many down votes out there in the answers. – Augustin Riedinger Mar 14 '18 at 13:04
  • I think a better way for 4 would be `callback = () => void 0`. It resolves to `undefined` and we are returning explictly and also leaving empty { } will give errors in eslint and jslint. – hashinclude72 Mar 10 '21 at 09:53

3 Answers3

10

Calling directly Function() constructor looks meaningful:

let myFunc = (callback = Function()) => {
  // do something...
  callback();
}

Calling Function() returns a noop function:

let noopFunc = Function()
noopFunc() // => undefined
Dmitri Pavlutin
  • 18,122
  • 8
  • 37
  • 41
3

Here is another option.

5 Just an if check..

  if (callback) callback(); 

If you want to prevent calling the callback twice, another utility function here I've called callIt, it also handles passing arguments, and if this is important also to prevent using bind, just pass this..

function callIt(that, fn) {
  if (fn) fn.apply(that, Array.prototype.slice.call(arguments,2));
}


//Test Object
function Test() {
  this.test = 'Test';
}

Test.prototype.calltest = function (callback) {
  callIt(this, callback, 1, 2, 3);
}

var t = new Test();
t.calltest(
  function (a,b,c) { 
    console.log('this.test = ', this.test); 
    console.log('args = ', a, b, c);
  }
);
Community
  • 1
  • 1
Keith
  • 22,005
  • 2
  • 27
  • 44
-1

// ES6 way:(default parameters)

function(callback=()=>{}) {
    if(typeof callback === 'function') {
        callback();
    }
}
Vijayraj
  • 193
  • 1
  • 5
  • 5
    If you do `typeof callback` anyway, why have a default value? – Felix Kling Nov 30 '16 at 15:00
  • I thought I tried this before but apparently not. I'm accepting yours because this is certainly the most natural. – Augustin Riedinger Nov 30 '16 at 15:08
  • @FelixKling `typeof` checks if the passed `callback` parameter is a function, not if the default value is a function. – Pierre Spring Aug 13 '20 at 07:39
  • 1
    @PierreSpring: Of course. That's not what my comment was implying. My point is that if you are already verifying the type of the argument, then there is no need to specify an empty function as default value. – Felix Kling Aug 13 '20 at 10:05