为什么Array.prototype.reduce没有thisObject参数? [英] Why does Array.prototype.reduce not have a thisObject parameter?

查看:102
本文介绍了为什么Array.prototype.reduce没有thisObject参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Javascript Array methods such as forEach have a thisArg parameter, which is used as the context for invoking the callback:

array.forEach(callback[, thisArg])

每个一些过滤器 map 。但是, reduce reduceRight 没有这样的参数。是否有某些特殊原因,或某些原因没有必要?

as do every, some, filter and map. However, reduce and reduceRight have no such parameter. Is there some particular reason for this, or some reason it is not necessary?

例如,考虑使用 reduceRight <的函数组合的以下实现/ code>:

For instance, consider the following implementation of functional composition using 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 返回的函数的上下文中调用compos。目前,它们似乎是在全局对象的上下文中调用的。我可以在函数 result 的顶部执行旧的 var self = this; ,并将其用作第一个参数到 cur.apply 调用,我目前有这个,但如果 reduce 拿了 thisArg 参数。

I would like to make this "this-aware", so the functions being composed are called in the context in which the function returned by compose is invoked. Currently they appear to be invoked in the context of the global object. I could do the old var self=this; at the top of function result, and use that as the first argument to the cur.apply call, where I currently have this, but that would be unnecessary if reduce took a thisArg argument.

我在这里遗漏了什么,是有什么关于减少这使得这不必要或无用吗?

Am I missing something here, and is there something about reduce that makes this unnecessary or unuseful?

更新

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

@kangax Yes, that occurred to me. Far be it from me to criticize the design of the API, but the signature for reduce seems a bit strange to me. The second optional argument functions differently than normal optional arguments, which typically just have a default value; instead its presence or absence changes the behavior, essentially overloading the function based on signature (argument count). When the second parameter is absent, the first element of the array becomes the starting value and the first call to the callback is against the second value. It seems to me that this behavior could be easily emulated by simply calling

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

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

instead of building in special rules for the case where the second argument is omitted, which in turn, if your presumption is correct, also made it essentially impossible to figure out where to specify the thisArg argument. Then again, I am sure such issues were already debated while the spec was being hashed out, and there may be good reasons for such an approach.

推荐答案

两个可选参数变得混乱,因为 reduce Right )已经涵盖了两个功能(参见维基百科),以纯语言着称(例如在Haskell中命名为 foldl foldl1 。引用 Brendan Eich

It becomes messy with two optional arguments, since reduce(Right) already covers two functionalities (see Wikipedia), which are distinguished in pure languages (e.g. named foldl and foldl1 in Haskell). To cite Brendan Eich:


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

So this would mean reduce takes one callback argument and two optional arguments: thisObject and init. Which one should come first? The more common one is probably init, but then you separate the callback arg from the "thisObject" arg, which is maybe okay. Multiple optional arguments are kinda messy this way...

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

Alternatively, we could just eliminate that extra "thisObject" argument, since people can always [use binding].

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

I don't think it's a big issue, since these functional higher-order-functions are mostly used with lamdba-function-expressions anyway (like in your example). Of course there's a little inconsistency, but we can live with that. Image the alternative:

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

无法真正使用,我们无法真正确定 如果提供了initialValue ,因为这意味着 arguments.length< 2 - 我们也可以传递 undefined 。这意味着

Can't be really used, we cannot really determine "if an initialValue was provided" since that means arguments.length < 2 - we could pass undefined literally as well. So that means

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

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

which is ugly since we always needed to pass null or something to thisArg if we only wanted an initial value.

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

You noticed that already in your comment to Kangax ("The second optional argument functions differently than normal optional arguments, […] its presence or absence changes the behavior"), but I can't support your statement


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

因为a)不适用于复杂(链式)表达式而不是数组变量和b )很麻烦。

as that would a) not work with a complex (chained) expression instead of the array variable and b) is cumbersome.

这篇关于为什么Array.prototype.reduce没有thisObject参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆