how JavaScript partially applied function – How to bind only the 2nd parameter?

 

Questions


Sorry if I’m missing something obvious, but I can’t figure out how to bind a specific (nth) argument of a function in javascript. Most of my functional programming I’ve learned has been from Scala so I’m not sure this is even possible in JS.

For example, I understand I can do the below to bind the 1st argument

var add = function (a, b) {
   return a + b;
};

add(1, 3); //returns 4

var addThree = add.bind(null, 3);  //this = null.  a = 3
addThree(4);                        //returns 7

But how can I bind the 2nd argument and leave the first as is. In other words how can I bind to ‘b’ only?

From what i can tell from mozilla – https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind , the arguments are actually nested which makes it look like it has to be in specific order? (I’m very possibly reading this wrong)

Edit:
I realize this is a sort of contrived example. I’m just trying to learn in case I eventually deal with something more complex than adding 2 numbers. I’m also trying to understand how the bind() arguments are actually working under the hood.

 

 

————————————————-

Answer

Of course you can do it. Here’s an ES6 solution using the spread operator (...), since it’s a bit more compact.

// Bind arguments starting after however many are passed in.
function bind_trailing_args(fn, ...bound_args) {
    return function(...args) {
        return fn(...args, ...bound_args);
    };
}

If you’d prefer to specify the position at which binding starts:

// Bind arguments starting with argument number "n".
function bind_args_from_n(fn, n, ...bound_args) {
    return function(...args) {
        return fn(...args.slice(0, n-1), ...bound_args);
    };
}

IN ES5, you have to muck around with constructing argument lists.

// ES5 version: construct arguments lists yourself
function bind_trailing_args(fn) {
    var bound_args = [].slice.call(arguments, 1);
    return function() {
        var args = [].concat.call(arguments, bound_args);
        return fn.apply(this, args);
    };
}

Unlike the first two examples, this one handles this properly.

In the context of your example:

var addThree = bind_trailing_args(add, 3);
addThree(1) // calls add(1, 3)

You could also consider using one of the functional programming libraries available for JS, such as http://osteele.com/sources/javascript/functional/. The thing you want is called rcurry there.

javascript

Facebook Comments

Post a comment