为什么使用.reduce而不是reduce()?使用JavaScript展平数组数组

时间:2014-08-25 01:15:45

标签: javascript arrays flatten

此示例来自http://eloquentjavascript.net/code/#5.1。 我的问题是第一个子弹头细节;其他可能是有用的细节,但是是额外的;还看到了第一个在上下文中查看我的问题的简短程序。

- 为什么arrays.reduce()代替reduce(arrays())而使用arrays.reduce。我知道他们可以使用var arrays = [[1, 2, 3], [4, 5], [6]]; console.log(arrays.reduce(function(flat, current) { return flat.concat(current); }, [])); // → [1, 2, 3, 4, 5, 6] ,但为什么呢?

这是一个有用的评论的答案,但除了原始问题之外。

  • 我的问题是第一个程序。因为它使用arrays.reduce, reduce会是一个数组的方法,我不知道为什么reduce是一个 数组方法。原因可能在于设计决策 JavaScript的?谢谢@cookie怪物的评论!

这是带有我的问题背景的程序 -

[]

这些下一个细节是附加的,但可能(或可能不是)有用:

我知道最后使用了.concat,因为它是函数reduce中的start参数,因此其他数组被添加到该空数组中。我知道+正在将两个数组(如function reduce(array, combine, start){ var current = start; for(var i = 0; i < array.length; i++) current = combine(current, array[i]); return current; } 与字符串放在一起,但对于数组。以下是reduce函数,即使它是标准的,看起来像:

console.log(reduce([1, 2, 3, 4], function(a, b){
  return a + b;
}, 0));
//  10

如果有帮助的话,他们的另一个例子展示了我使用单个数组的方法。看起来像是:

{{1}}

谢谢! :)

2 个答案:

答案 0 :(得分:2)

JavaScriptScheme方言的影响Lisp。方案higher order functions是该语言的组件/功能。事实上,reduce函数几乎等同于Scheme中的fold函数。对于JavaScript中的reduce函数,该语言的创建者注意到程序员经常需要以某种方式遍历数组,并为程序员提供更高阶函数,他们可以通过在函数中指定他们想要如何操纵数据。具有更高阶的函数允许程序员抽象冗余代码,从而创建更短,更清晰,更易读的代码。

您可以使用JavaScript中的reduce函数执行除展平列表之外的许多操作。看here一个例子。

答案 1 :(得分:2)

在面向对象的设计中,指导原则是您创建或声明对象,并且这些对象在其上具有一系列对该特定类型的对象进行操作的方法。由于Javascript是面向对象的语言,因此内置函数遵循许多面向对象的原则。

.reduce()是一个仅在Arrays上运行的函数。没有阵列可以操作是没用的。因此,在面向对象的设计范例中,将.reduce()函数作为方法放在Array对象上是完全合理的。

与全局reduce()函数相比,这种面向对象的方法具有以下优势:

  1. 这与语言中其他地方使用的面向对象原则一致。
  2. 使用.reduce()调用特定array上的array.reduce()函数很方便,从语法中可以明显看出它正在运行的数组。
  3. 所有数组操作都被分组为Array对象上的方法,使API定义更加自我记录。
  4. 如果您尝试执行obj.reduce()(在非数组上调用它),您将立即收到有关未定义.reduce()方法的运行时错误。
  5. 全局范围内没有额外的空间(例如,没有定义额外的全局符号 - 减少意外覆盖或与其他代码冲突的机会)。

  6. 如果您想知道为什么有人曾使用过全局reduce(),那么您需要了解一下Javascript演变的历史。在ES5之前(或者对于运行尚未实现像IE8这样的ES5的浏览器的用户),Javascript在.reduce()对象上没有内置的Array方法。然而,一些熟悉其他语言的这种有用迭代功能的开发人员希望在他们自己的Javascript或他们自己的Javascript框架中使用它。

    如果要在Javascript中为Array这样的现有内置对象添加一些功能,通常有两种选择。您可以向原型添加方法(以面向对象的方式),也可以创建一个以Array作为第一个参数的全局函数。

    特别是对于Array对象,向Array原型添加可迭代方法存在一些潜在问题。这是因为如果任何代码执行这种类型的数组迭代(迭代数组的一种坏方法,但仍由许多人完成):

    for (var prop in array)
    

    它们最终不仅会迭代数组的元素,还会迭代数组的任何可迭代属性。如果使用这种语法为原型分配了一个新方法:

    Array.prototype.myMethod = function() {}
    

    然后,这个新方法将最终使用for (var prop in array)语法进行迭代,这通常会导致问题。

    因此,不是在原型中添加新方法,而是使用全局函数来避免此问题,而不是添加新方法。

    从ES 5.1开始,有一种方法可以使用Object.defineProperty()向对象或原型添加不可迭代的方法,因此对于较新的浏览器,现在可以将方法添加到不受上面提到的问题。但是,如果您想支持旧浏览器(如IE8)并使用reduce()类型的功能,您仍然会遇到这些古老的限制。

    所以......即使全局reduce()不是面向对象的,并且在Javascript中通常不那么理想,但由于合法的安全性/互操作性原因,一些旧的代码走了这条路线。幸运的是,我们正在把这条道路放在我们身后,因为IE的旧版本在使用中下降(感谢上帝为微软放弃XP支持以最终加速旧版IE的消亡)。较新的浏览器已内置array.reduce()