2

What's the most efficient/the best practice for passing a Javascript function with parameters without executing it, and why? Here is the choice I know :

Make a anonymous method

jQuery("#target").click(function() {
    onTargetClick("myCoolParam");
});

function onTargetClick(coolParam) {
    // some epic code...
}

Use partial function application (See: Partial function application)

jQuery("#target").click(partial(onTargetClick, "myCoolParam"));

function onTargetClick(coolParam) {
    // some epic code...
}

function partial(func /*, 0..n args */) {
    var args = Array.prototype.slice.call(arguments).splice(1);
    return function() {
        var allArguments = args.concat(Array.prototype.slice.call(arguments));
        return func.apply(this, allArguments);
    };
}

EDIT for the partial function

function partial(func /*, 0..n args */) {
    var args = Array.prototype.slice.call(arguments, 1);
    return function() {
        var allArguments = args.concat(Array.prototype.slice.call(arguments));
        return func.apply(this, allArguments);
    };
}

Thank you for your help.

Community
  • 1
  • 1

2 Answers2

2

I would use Function.prototype.bind which allows to pass additional parameters:

jQuery("#target").click(onTargetClick.bind(null, "myCoolParam"));
dfsq
  • 191,768
  • 25
  • 236
  • 258
  • So, with `bind`, you have to specify the `this` parameter at binding time? – Samuel Edwin Ward Feb 19 '15 at 16:12
  • @SamuelEdwinWard: Yes. JavaScript doesn't currently have a built-in curry function that doesn't require the thisArg (which surprised me; when they added `bind`, which PrototypeJS had been adding for years, they chose not to add `curry`, which was also well-represented in prior art). – T.J. Crowder Feb 19 '15 at 16:12
  • @T.J.Crowder *JavaScript doesn't currently have a built-in curry function that doesn't require the thisArg*. Do you imply arrow function from ES6? – dfsq Feb 19 '15 at 16:15
  • @dfsq: No, lexical `this` binding is a separate topic. I meant something like the OP's `partial` or PrototypeJS's `curry`, which unlike `bind` use the `this` the resulting function called with. – T.J. Crowder Feb 19 '15 at 16:17
2

It depends

Using a wrapper function as in your first example is direct, easy to read, pragmatic, and on modern engines unlikely to have unpleasant side-effects related to being a closure over the context you're using it in (because modern engines optimize trivial closures in many cases). With older engines, that didn't optimize closures, it could have lead to things being kept in memory unnecessarily (and still could, with a more complex closure; but one such as yours which doesn't use eval, new Function, or with, and which references just one variable presumably not declared in the immediately-containing context, is a good candidate for optimization).

Using JavaScript's Function#bind avoids the closure issue; is a bit more concise; and is likely, on modern engines, to be extremely efficient (while not being inefficient on older engines where it needs to be polyfilled). It does muck up the this value, though, which can be a problem in event handlers (although you weren't using this in your example).

Using a function like your partial or PrototypeJS's Function#curry also has the benefits of avoiding the closure issue and being concise, is unlikely to be inefficient, and uses the this value that was given to the function they generate. They have the downside of not being standard, so you have to provide them and people reading your code have to understand what they do.

Take your choice.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875