17

Javascript Array 方法,例如forEach有一个thisArg参数,用作调用回调的上下文:

array.forEach(callback[, thisArg])

every,some和一样。但是,并没有这样的参数。有什么特别的原因,还是没有必要的原因?filtermapreducereduceRight

例如,考虑以下使用 的功能组合实现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];
    };
}

我想让它成为“this-aware”,因此正在组合的函数在调用返回的函数的上下文中compose调用。目前,它们似乎是在全局对象的上下文中调用的。我可以var self=this;在 function 的顶部做 old result,并将其用作cur.apply调用的第一个参数,我目前有,但如果带一个参数this,那将是不必要的。reducethisArg

我是否在这里遗漏了一些东西,是否有一些东西reduce使这变得不必要或无用?

更新

@kangax 是的,这发生在我身上。我绝不会批评 API 的设计,但 for 的签名对reduce我来说似乎有点奇怪。第二个可选参数的功能与普通可选参数不同,后者通常只有一个默认值;相反,它的存在或不存在会改变行为,本质上是基于签名(参数计数)重载函数。当第二个参数不存在时,数组的第一个元素成为起始值,第一次调用回调是针对第二个值。在我看来,这种行为可以很容易地通过简单地调用来模拟

array.slice(1).reduce(fn,array[0])

而不是为省略第二个参数的情况建立特殊规则,如果你的假设是正确的,这反过来也使得基本上不可能弄清楚在哪里指定thisArg参数。再说一次,我确信在规范制定时已经对此类问题进行了辩论,并且可能有充分的理由采用这种方法。

4

4 回答 4

5

您始终可以使用此方法:

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

...为了将特定的上下文附加到回调函数。

于 2017-03-21T13:18:33.667 回答
4

由于reduce( Right) 已经涵盖了两个功能(参见Wikipedia),因此两个可选参数会变得混乱,这在纯语言中是有区别的(例如,命名foldlfoldl1在 Haskell 中)。引用Brendan Eich 的话

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

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

我认为这不是一个大问题,因为无论如何这些功能性高阶函数大多与lamdba -function-expressions 一起使用(就像在您的示例中一样)。当然有一点不一致,但我们可以忍受。图像替代:

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

不能真正使用,我们无法真正确定“是否提供了 initialValue ”,因为这意味着- 我们也可以按字面意思arguments.length < 2传递。undefined所以这意味着

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

这很丑陋,因为如果我们只想要一个初始值,我们总是需要传递null或传递一些东西。thisArg

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

只需调用即可轻松模拟此行为array.slice(1).reduce(fn,array[0])

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

于 2013-02-16T17:37:08.713 回答
4

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

其他带有回调的方法采用 'thisArg' 不是因为它是必需的,甚至是有用的,而是为了兼容性,因为它们已经在提供这些函数的现有实现中这样做了。

于 2013-02-16T15:03:12.500 回答
1

不需要 thisObject 参数,因为您可以在累加器中添加一种 thisObject 并使用初始值传递 thisObject。

例子:

thisObj = { some data }  // kind of this arg to be used in the reducer
const { view, used, totals } = sheetConfig.reduce(reducer, {
  view: [],    // initial  
  used: [],    // another initial
  totals: [],  // and one more initial
  thisObj      // and ...
});
于 2021-11-13T16:11:15.567 回答