请停止对 Array.reduce() 的恶意攻击
2023-07-24 18:23:28 129浏览
【编者按】这篇文章主要讨论了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() 是 JavaScript 中的一个数组函数,是一个对数组中的每个元素按顺序执行一个提供的回调函数,并将它们累计为一个单一的返回值的方法。
下面是该函数的一个简单示例:
const value = [1,2,3,4].reduce((acc, cur) => {
return acc + cur;
}, 0);
// value: 10
这个函数接收两个参数:
callback:一个回调函数,即 reducer
initialValue:累积值的初始值
回调函数接受 4 个可选参数:
accumulator:累积值
currentValue:你正在遍历的数组的当前项
currentIndex:你正在遍历的数组的当前索引
array:你正在遍历的整个数组
一个完整的签名看起来像这样:
const reducer = (accumulator, currentValue, currentIndex, array) = > {
return accumulator;
}
const value = [...].reduce(reducer, 0)
问题出在哪里?
在翻阅这些抱怨之后,一个普遍的抱怨是:Array.reduce() 太难阅读和理解了。
在审查代码、扫描新的代码库或阅读文档时,遇到 Array.reduce() 需要你停下来,花一会儿时间思考数组到底发生了什么。
因为,你可以使用另一种 Array 方法如 Array.forEach() 或者简单的 for 循环,以更易读的方式达到同样的结果。
虽然这些观点提的很好,但它们是错的!
我的理由
当我阅读这些评论时,我想到了一些事情。我认为这些观点背后的很多理由都非常有道理!但是,他们吐槽的焦点被引向了错误的方向。
我对此事的首要想法是,真正的问题并不在于方法签名和复杂性,而是在于开发者最大的敌人:命名问题。
实际上,我认为这个问题在争议中根深蒂固,以至于它以两种不同的方式显现出来!
展示 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 方法是一样的,都是对数组的每个元素执行一个函数,并返回一个累积的结果,那么问题就瞬间解决了。
显然,这只是一个玩笑。一个完全解决问题的玩笑,但仍然只是一个玩笑。
展示 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() 理解为一个不仅可以将数组累计为一个单一的值,还具有其他功能的强大的函数,就更容易理解了。
我看到的很多问题都是用户在命名上犯的错误。比如,用不恰当的变量名或函数名,导致代码难以理解或出现 bug。
对这个问题你怎么看?你同意我的看法吗?
附加问题:
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);
你赞成这么做吗?
推荐阅读:
▶iPhone 15 或推迟上市;谷歌软件工程师基本年薪达 71.8 万美元;Godot 4.1.1 发布|极客头条
好博客就要一起分享哦!分享海报
此处可发布评论
评论(0)展开评论
展开评论
您可能感兴趣的博客