对象函数的javascript curry / partial函数调用

时间:2011-10-14 15:17:56

标签: javascript

我想要一个'咖喱'之类的功能 - 这种事情

function invoker (fn) {
    var slice = Array.prototype.slice,
        args = slice.apply(arguments, [1]);
    return function () {
       return fn.apply(null, args);
    };
}

但我希望用户能够做到

invoker(f)

invoker(foo.bar)

我无法找到正确的魔法咒语来做到这一点。我看到的所有示例都要求范围对象单独传递;这容易出错并且不自然。 IE

invokerx(foo.bar, foo)

到底有没有这样做?我不介意有两个不同的功能

invokeG(f)
invokeO(foo.bar)

编辑:澄清

'f' is a global scope function
'foo' is an object
'bar is a method on that object

IE我希望这个咖喱工具能够使用“自由”功能以及对象功能。

必须去

<curry function>(foo.bar,foo)

看起来有点笨重,我不得不说'foo'两次

2 个答案:

答案 0 :(得分:4)

apply的第一个参数是函数可用的this。由于您传递了nullthis将被映射到window

以下修改将起作用:

function invoker (fn, target) {
    var slice = Array.prototype.slice,
        args = slice.apply(arguments, [2]);

    if(typeof fn === 'string')
        fn = (target || window)[fn];

    return function () {
       return fn.apply(target || null, args);
    };
}

// Either will work:
invoker(foo.bar, foo);
invoker('bar', foo);

// Any of these will work:
invoker(escape, null);
invoker(escape, window);
invoker('escape', null);
invoker('escape', window);

UPDATE 添加了一些细微的更改,以添加对名称传递的支持,因此您不必两次传递对象名称。

更新2 由于我们正在讨论,我们需要总是有两个参数。

答案 1 :(得分:2)

你做不到。执行invoker(foo.bar)时,invoker无法知道参数是foo的成员函数。函数不存储它们的“所有者”,invoker只传递对函数的引用。

最接近的是使用function.bind(),如下所示:

invoker(foo.bar.bind(foo))