天天看点

请停止对 Array.reduce() 的恶意攻击

作者:CSDN
请停止对 Array.reduce() 的恶意攻击

【编者按】这篇文章主要讨论了JavaScript 开发者是否应该使用 Array.reduce() 方法这个争议。作者认为,尽管有些人认为Array.reduce() 方法难以阅读和理解,但这主要是由于命名习惯的问题,而不是方法本身的问题。Array.reduce() 是一个强大的函数,可以做的远不止将数组每个元素执行一个操作,并返回一个累积的结果。作者通过举例和解释,阐述了他的观点,并对如何更好地使用 Array.reduce() 提出了建议。

原文链接: https://www.devchronicles.io/array-reduce-is-good/

未经允许,禁止转载!

作者 | SABIN ADAMS 译者 | 明明如月责编 | 夏萌出品 | CSDN(ID:CSDNnews)

最近 “JavaScript 开发者是否应该使用 Array.reduce() ”的话题, 在网上引发了很大争论。

下面是最近一次关于该问题的激烈讨论中的部分帖子:

“大家都承认 Array.reduce 是一个错误吗?” - rossipedia

“Epic Stack 在三个地方使用了 reduce,我并不感到羞耻。Array.reduce 很好。” - Kent C. Dodds

“虽然这个观点可能不讨喜,但我真的很讨厌 Array.reduce。我还发现,一个人越是愚蠢,他们就越认为 Array.reduce 是“有意义”和“重要”的。” - Chris Esplin

当然,每个人都可以有自己的观点!这篇文章旨在说明为什么所有认为 Array.reduce() 不好的观点都是错误的 😈。

免责声明:说Array.reduce 不好的人并没有错 😅 ,只是我跟他们一样固执!
请停止对 Array.reduce() 的恶意攻击

这个函数是干什么的?

Array.reduce() 是 JavaScript 中的一个数组函数,是一个对数组中的每个元素按顺序执行一个提供的回调函数,并将它们累计为一个单一的返回值的方法。

下面是该函数的一个简单示例:

const value = [1,2,3,4].reduce((acc, cur) => {              return acc + cur;              }, 0);                  // value: 10           

这个函数接收两个参数:

  1. callback:一个回调函数,即 reducer
  2. initialValue:累积值的初始值

回调函数接受 4 个可选参数:

  1. accumulator:累积值
  2. currentValue:你正在遍历的数组的当前项
  3. currentIndex:你正在遍历的数组的当前索引
  4. array:你正在遍历的整个数组

一个完整的签名看起来像这样:

const reducer = (accumulator, currentValue, currentIndex, array) = > {              return accumulator;              }                  const value = [...].reduce(reducer, 0)           
请停止对 Array.reduce() 的恶意攻击

问题出在哪里?

在翻阅这些抱怨之后,一个普遍的抱怨是:Array.reduce() 太难阅读和理解了。

在审查代码、扫描新的代码库或阅读文档时,遇到 Array.reduce() 需要你停下来,花一会儿时间思考数组到底发生了什么。

因为,你可以使用另一种 Array 方法如 Array.forEach() 或者简单的 for 循环,以更易读的方式达到同样的结果。

虽然这些观点提的很好,但它们是错的!

请停止对 Array.reduce() 的恶意攻击

我的理由

当我阅读这些评论时,我想到了一些事情。我认为这些观点背后的很多理由都非常有道理!但是,他们吐槽的焦点被引向了错误的方向。

我对此事的首要想法是,真正的问题并不在于方法签名和复杂性,而是在于开发者最大的敌人:命名问题。

实际上,我认为这个问题在争议中根深蒂固,以至于它以两种不同的方式显现出来!

请停止对 Array.reduce() 的恶意攻击

展示 A:它不应该被命名为 reduce

首先,这个方法被命名为 reduce。虽然在很多情况下这个方法名是有道理的。但 Array.reduce() 方法非常强大,它可以做的远不止将数组减少到一个单一的值。

考虑一下下面的函数使用方法:

const smallNumbers = [1,2,3,4,5];              const largeNumbers = smallNumbers.reduce((newArray, current) => {              newArray.push(current ** 2);              return newArray;              }, []);                  // largeNumbers: [1,4,9,16,25]           

在这种情况下,我们并没有减少初始数组的长度。我们在 转换 它!所以,这就是足够让人讨厌 Array.reduce() 的理由吗?我并不这么认为!

Array.prototype.transform = Array.prototype.reduce;           

如果我们给数组的原型对象添加一个 transform 方法,这个方法和 reduce 方法是一样的,都是对数组的每个元素执行一个函数,并返回一个累积的结果,那么问题就瞬间解决了。

显然,这只是一个玩笑。一个完全解决问题的玩笑,但仍然只是一个玩笑。

请停止对 Array.reduce() 的恶意攻击

展示 B:人们在命名参数时偷懒

你有多少次见过下面这样的循环:

const array = [...];              let crazyValue = 0;              for (let i = 0; i < array.length; i++) {              for (let j = 0; j < i; j++) {              crazyValue = i + j;              }              }           

i 和 j 代表什么?为什么这些单字符变量名这么常见,以至于看起来几乎是正常的?

同样(恶心)的问题存在于 Array.reduce() 的使用中。你会经常看到这样的代码:

const array = [...];              const crazyValue = array.reduce((acc, curr, i, arr) => {              return acc + curr;              }, 0)           

acc、curr、i 和 arr 是什么意思?我们可以通过更具描述性的变量名来解决这个令人困惑的问题:

const array = [...];              const crazyValue = array.reduce((total, currentValue, index, originalArray) => {              return total + currentValue;              }, 0)           

或者再进一步优化:

const array = [...];              const initialValue = 0;              const addValues = (total, currentValue, index, originalArray) => {              return total + currentValue;              }                  const crazyValue = array.reduce(addValues, initialValue)           

这可能不是完美的解决方案,但它肯定使代码更容易阅读和理解。

请停止对 Array.reduce() 的恶意攻击

你怎么看?

Array.reduce() 真有那么糟糕吗?我并不这么认为。如果你将 Array.reduce() 理解为一个不仅可以将数组累计为一个单一的值,还具有其他功能的强大的函数,就更容易理解了。

我看到的很多问题都是用户在命名上犯的错误。比如,用不恰当的变量名或函数名,导致代码难以理解或出现 bug。

对这个问题你怎么看?你同意我的看法吗?

请停止对 Array.reduce() 的恶意攻击

附加问题:

Array.prototype.transform = Array.prototype.reduce;              const add = (total, current) => total + current;              const initialValue = 0;              const sumOfNumbers = [1,2,3,4,5].transform(add, initialValue);           

你赞成这么做吗?