开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情 Lo友们大家好!
摘要
使用原生js对Lodash工具库方法进行解析并扩展,本文详细解析_.chunk的使用及背后原理,并扩展reduce和slice的使用
_.chunk的使用
_.chunk(array, [size=1])将数组(array)拆分成多个
size长度的区块,并将这些区块组成一个新数组。 如果array无法被分割成全部等长的区块,那么最后剩余的元素将组成一个区块。参数
array(Array) : 需要处理的数组[size=1](number) : 每个数组区块的长度返回
(Array) : 返回一个包含拆分区块的新数组(注:相当于一个二维数组)。
以上是Lodash_.chunk的使用方法,以下是原生实现:
const chunk = (arr, size) => { // 同样传入需要处理的数组和想要的数组区块长度
return arr.reduce((previousValue, currentValue, currentIndex, array) => { // 使用reduce进行数组遍历
return index % size === 0 // 根据数组长度判断是否分块
? [...previousValue, [currentValue]] // 将当前currentValue单独分块
: [...previousValue.slice(0, -1), [...previousValue.slice(-1)[0], currentValue]] // 合并区块,只将currentValue放到最后一个区块
}, [])
};
以上注释可能有些生涩,我们再来逐行讲解,这里指的区块是二维数组中的元素,其实就是个数组。 举个例子:
chunk(['A', 'B', 'C', 'D', 'E', 'F', 'G'], 3)
// result [['A', 'B', 'C'], ['D', 'E', 'F'], ['G']]
先简单介绍一下所用到的方法,已了解也可温习一下
reduce((previousValue, currentValue, currentIndex, array) => {/* … */}, initialValue)
- previousValue: 上一次调用箭头函数时的返回值。在第一次调用时,若指定了初始值
initialValue,其值则为initialValue,否则为数组索引为 0 的元素array[0]。 - currentValue: 数组中正在处理的元素。在第一次调用时,若指定了初始值
initialValue,其值则为数组索引为 0 的元素array[0],否则为array[1]。 - currentIndex: 数组中正在处理的元素的索引。若指定了初始值
initialValue,则起始索引号为 0,否则从索引 1 起始。 - array: 用于遍历的数组。
slice(start, end)
- start(可选):提取起始处的索引(从
0开始),从该索引开始提取原数组元素。如果该参数为负数,则表示从原数组中的倒数第几个元素开始提取,slice(-2)表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)。如果省略start,则slice从索引0开始。如果start超出原数组的索引范围,则会返回空数组。 - end(可选): 提取终止处的索引(从
0开始),在该索引处结束提取原数组元素。slice会提取原数组中索引从start到end的所有元素(包含start,但不包含end)。slice(1,4)会提取原数组中从第二个元素开始一直到第四个元素的所有元素(索引为 1, 2, 3 的元素)。如果该参数为负数,则它表示在原数组中的倒数第几个元素结束抽取。slice(-2,-1)表示抽取了原数组中的倒数第二个元素到最后一个元素(不包含最后一个元素,也就是只有倒数第二个元素)。如果end被省略,则slice会一直提取到原数组末尾。如果start大于数组的长度,slice也会一直提取到原数组末尾。
接下来我们解析一下以下三行代码究竟做了什么
return index % size === 0
? [...previousValue, [currentValue]]
: [...previousValue.slice(0, -1), [...previousValue.slice(-1)[0], currentValue]]
第一行通过下标对size取余,判断二维数组中是否已经有满足长度size的区块(数组),如果当前previousValue(二维数组)内已经有长度为size的倍数的区块(数组),执行第二行,否则,执行第三行
先看第三行,previousValue.slice(0, -1)抽取二维数组中除了最后一个数组的所有数组,并通过扩展运算符将所有数组取出来;如果previousValue中只有一个数组,previousValue.slice(0, -1)返回的就是[];
previousValue.slice(-1)[0]就是抽取二维数组中最后一个数组并取出数组,通过扩展运算符将数组中的值取出来与currentValue合并成一个新的数组元素,即[...previousValue.slice(-1)[0], currentValue];
第三行的意思就是,将当前正在处理的元素添加到二维数组中最后一个数组里面
回到第二行,如果index % size === 0,说明二维数组中已经有满足长度为size的区块了,所以只需要将当前currentValue放到一个新的数组区块里面。
第二行的意思就是,将当前正在处理的元素添加到二维数组中新建一个数组里面
所以,整体的逻辑出来了。这里不做例子输出展示,留给大家自己打开F12在控制台中尝试一下,因为可能你只是眼睛懂了
扩展阅读
You-Dont-Need-Lodash-Underscore本篇文章源码主要参考自此
25个你不得不知道的数组reduce高级用法这篇文章写的很全,我就引用一下吧
小结
用最啰嗦的言语解析每行代码,力求人人都能看懂,持续更新Lodash的100多个工具方法的使用和实现,一起学习,一起进步
~( ̄︶ ̄)↗点赞