lodash.js在function.apply上的部分应用程序

时间:2014-03-12 20:27:27

标签: javascript functional-programming underscore.js lodash

鉴于以下函数,_.partial函数的使用会引发错误:

function foo(x, y) { return 1 + 2; }
p = _.partial(foo.apply, null);
p([1,2]);

我明白了:

  

TypeError:在[object Window]上调用了Function.prototype.apply,它是一个对象而不是一个函数

我在这里做错了什么?还有另一种方法来实现我正在做的事情吗?

3 个答案:

答案 0 :(得分:3)

我相信你的目标:

function foo(x, y) { return x + y; }
p = Function.apply.bind(foo, null);
p([1,2]); // ===3

最接近我可以通过_.bind得到下划线:

function foo(x, y) { return x + y; }
p = _.bind(foo.apply, foo, 0);
p([1,2]); // ===3

您可能还想考虑另一个灵活使用该函数,对两个以上元素的整数数组求和:

 function foo(x, y) { return x + y; }
_.reduce([1,2,3,4,5], foo); // == 15

或使用vanillaJS:

function foo(x, y) { return x + y; }
[1,2,3,4,5].reduce(foo); // == 15

答案 1 :(得分:2)

冒着误解这个问题的风险,我想分享一个我偶然发现类似情况的策略。

问题:

在我的例子中,问题是有时我需要使用一些参数调用函数(foo)而不更改this上下文。不幸的是,参数列表不是确定性的 - 有时候可能有2个,有时可能有3个等等。而且由于_.partial期望每个参数作为一个单独的参数传递,我最初被难倒了。例如:

// some dynamic array of args
var args = [new Error(), [{id: 3}, {id: 7}], function cb() {}];

// the function we want the partially applied to
var fn = function foo ( /* ...want `args` in here... */ ) {
  // ..implementation...
}

// can't do it with normal _.partial() usage...
// var newFn = _.partial(fn, args[0], args[1], ... args[args.length])

解决方案:

当您想要使用apply而不是call来正常调用函数时,这是一个相同的用例。所以经过一段时间的闲逛之后,我意识到我可以做到:

var argsToLodashPartialFn = [foo].concat(args);
var newFn = _.partial.apply(null, argsToLodashPartialFn);

tldr;

或者,更简洁:

var newFn = partialApply(foo, args);

// === newFn(args[0], args[1], ...., args[n])
newFn();

这是作为可重用函数的实现:

/**
 * partialApply()
 *
 * Like `_.partial(fn, arg0, arg1, ..., argN)`,
 * but for a dynamic array of arguments:
 *
 * @param {Function} fn
 * @param {Array}    args
 * @return {Function}
 */

function partialApply (fn, args) {
  return _.partial.apply(null, [fn].concat(args));
}

答案 2 :(得分:1)

从lodash 3.2开始,您将使用spread()函数:

function foo(x, y) { return x + y; }
var p = _.spread(foo);
p([ 1, 2 ]); // → 3