JavaScript部分应用函数 - 如何只绑定第二个参数?

Jus*_*aat 38 javascript

很抱歉,如果我遗漏了一些明显的东西,但我无法弄清楚如何在javascript中绑定函数的特定(第n个)参数.我学到的大部分函数式编程都来自Scala,所以我不确定这在JS中是否可行.

例如,我知道我可以执行以下操作来绑定第一个参数

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
Run Code Online (Sandbox Code Playgroud)

但是我如何绑定第二个参数并保留第一个参数.换句话说,我怎么才能绑定'b'?

从我从mozilla可以看出 - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind ,参数实际上是嵌套的,这使它看起来像必须是按特定顺序?(我很可能读错了)

编辑:我意识到这是一个人为的例子.我只是想学习以防万一我最终处理比添加2个数字更复杂的事情.我也试图理解bind()参数实际上是如何工作的.

小智 34

当然你可以做到.这是使用扩展运算符(...)的ES6解决方案,因为它更紧凑.

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

如果您更愿意指定绑定开始的位置:

// 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);
    };
}
Run Code Online (Sandbox Code Playgroud)

在ES5中,你必须捣乱构建参数列表.

// 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);
    };
}
Run Code Online (Sandbox Code Playgroud)

与前两个示例不同,这个示例处理this得当.

在您的示例的上下文中:

var addThree = bind_trailing_args(add, 3);
addThree(1) // calls add(1, 3)
Run Code Online (Sandbox Code Playgroud)

您还可以考虑使用JS可用的函数编程库之一,例如http://osteele.com/sources/javascript/functional/.你想要的东西就rcurry在那里.


Ali*_*anC 30

您可以使用lodash _.bind来实现此目的:

var add = function(a, b) {
  document.write(a + b);
};

// Bind to first parameter (Nothing special here)
var bound = _.bind(add, null, 3);
bound(4);
// ? 7

// Bind to second parameter by skipping the first one with "_"
var bound = _.bind(add, null, _, 4);
bound(3);
// ? 7
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.9.3/lodash.min.js"></script>
Run Code Online (Sandbox Code Playgroud)

我通常反对库并且更喜欢编写我自己的实用程序函数,但是很容易为lodash做一个例外.我强烈建议你每当有"这必须使用某种语言时" 检查其文档!时刻.它在JavaScript中填补了很多空白.


Ben*_*min 11

好.我会把它扔出去.

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

var addThree = function(a) {
  return add(a,3);
};

add(1,2);
addThree(4);
Run Code Online (Sandbox Code Playgroud)

也许对一些人来说没问题.