为什么Array.prototype.reduce没有thisObject参数?

时间:2013-02-14 04:44:25

标签: javascript ecmascript-5

Javascript数组方法(如forEach)具有thisArg参数,该参数用作调用回调的上下文:

array.forEach(callback[, thisArg])

everysomefiltermap一样。但是,reducereduceRight没有此类参数。这有什么特别的原因,或某些原因没有必要吗?

例如,考虑使用reduceRight的以下功能组合实现:

function compose () {
    var fns = [].slice.call(arguments,0);
    return function result() {
        return fns.reduceRight(
            function (prev,cur){
                return [cur.apply(this,prev)];
            },
            arguments
        )[0];
    };
}

我想使这个“知道”,所以正在调用的函数在调用compose返回的函数的上下文中调用。目前,它们似乎是在全局对象的上下文中调用的。我可以在函数var self=this;的顶部执行旧的result,并将其用作cur.apply调用的第一个参数,我当前有this,但那样做如果reduce采用thisArg参数,则不必要。

我在这里遗漏了什么,有什么关于reduce会使这不必要或无用吗?

更新

@kangax是的,发生在我身上。对我来说,批评API的设计远非如此,但reduce的签名对我来说似乎有点奇怪。第二个可选参数的功能与普通的可选参数不同,后者通常只有一个默认值;相反,它的存在或不存在会改变行为,基本上会根据签名(参数计数)重载函数。当第二个参数不存在时,数组的第一个元素成为起始值,第一个对回调的调用是第二个值。在我看来,只需调用

就可以轻松模拟这种行为
array.slice(1).reduce(fn,array[0])

而不是为省略第二个参数的情况构建特殊规则,而这反过来,如果你的推定是正确的,那么也基本上不可能找出指定thisArg参数的位置。再说一次,我确信这些问题在规范被删除时已经有争议,并且可能有充分的理由采用这种方法。

3 个答案:

答案 0 :(得分:4)

两个可选参数变得混乱,因为reduceRight)已经涵盖了两个功能(参见Wikipedia),这两个功能在纯语言中有区别(例如名为foldl和Haskell中的foldl1)。引用Brendan Eich

  

所以这意味着reduce需要一个回调参数和两个可选参数:thisObject和init。哪一个应该先来?更常见的可能是init,但是你将回调arg与“thisObject”arg分开,这可能没问题。这样多个可选参数有点混乱......

     

或者,我们可以消除额外的“thisObject”参数,因为人们总是 [使用绑定]

我认为这不是一个大问题,因为这些功能性高阶函数主要用于 lamdba - 函数表达式(如在你的例子中)。当然有一点不一致,但我们可以忍受。想象一下:

 array.reduce(callback[, initialValue[, thisArg]])

无法真正使用,我们无法真正确定“if an initialValue was provided”,因为这意味着arguments.length < 2 - 我们也可以从字面上传递undefined。这意味着

 array.reduce(callback[, thisArg[, initialValue]])

这很难看,因为如果我们只想要一个初始值,我们总是需要将null或其他内容传递给thisArg

你注意到你已经在对Kangax的评论中(“第二个可选参数的功能与普通的可选参数不同,[...]它的存在或不存在会改变行为”),但我不能支持你的陈述

  

只需调用array.slice(1).reduce(fn,array[0])

即可轻松模拟此行为

因为a)不能使用复杂(链式)表达式而不是array变量而b)是麻烦的。

答案 1 :(得分:3)

在Es-discuss邮件列表中,您可以在回答http://article.gmane.org/gmane.comp.lang.javascript.ecmascript4.general/4770

中找到
  

使用回调的其他方法采用'thisArg'不是因为它   需要甚至有用,但为了兼容性,因为他们已经做到了   在提供这些功能的现有实现中。

答案 2 :(得分:3)

您始终可以使用此方法:

array.reduce(callback.bind(context), initialValue);

...以便将特定上下文附加到回调函数。