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

时间:2014-12-30 04:13:04

标签: 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

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

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

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

4 个答案:

答案 0 :(得分:31)

当然你可以做到。这是使用扩展运算符(...)的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);
    };
}

如果您希望指定绑定开始的位置:

// 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);
    };
}

在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);
    };
}

与前两个示例不同,此示例正确处理this

在您的示例中:

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

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

答案 1 :(得分: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

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.9.3/lodash.min.js"></script>
&#13;
&#13;
&#13;

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

答案 2 :(得分:9)

好。我把它扔到那里。

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

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

add(1,2);
addThree(4);

也许对某些人来说没问题。

答案 3 :(得分:0)

你可以试试这个:

Function.prototype.bindThemAll = function bindThemAll(thisArg, ...boundArgs) 
  (boundArgs.fn = this, function(...args) boundArgs.fn.call(thisArg || this, ...boundArgs.map((el) => el || args.shift()), ...args));

function fn() console.log("fn:", arguments.callee, "this:", this, "args:", arguments)

var x = {a: 5};

var bfn = fn.bindThemAll(x, null, 2)
bfn(1,3)
x.bfn = fn.bindThemAll(null, null, 2)
x.bfn(1,3)

带有null或undefined的绑定参数将按顺序替换为函数参数,其余参数将附加到结尾。 如果它被绑定将被使用,否则将使用当前的对象...

请参阅控制台了解结果!