以不正义开始的事情,必须用罪恶使它巩固。

——莎士比亚《麦克白》

最近很多事似乎印证了这句话,一句谎言最后要用一百句谎言来圆谎。

本文为读 lodash 源码的第二篇,后续文章会更新到这个仓库中,欢迎 star:pocket-lodash

gitbook也会同步仓库的更新,gitbook地址:pocket-lodash

作用与用法

chunk 函数可以将一个数组,切割成指定大小的块,返回由这些块组成的新数组。

chunk 函数在前端可以用来缓解一些性能问题。例如大量的 DOM 操作,可以分块让浏览器在空闲的时候处理,避免页面卡死。如下面的代码,向页面中插入大量的DOM。

const arr = [] // 1万条数据
const chunks = _.chunk(arr, 100) const append = function () {
if (chunks.length > 0) {
const current = chunks.pop()
current.forEach(item => {
const node = document.createElement('div')
node.innerText = item
document.body.appendChild(node)
})
setTimeout(append, 0)
}
} append()

依赖

import slice from './slice.js'

读lodash源码之从slice看稀疏数组与密集数组

原理

chunk 的原理归结起来就是切割和放置。

chunk 最后返回的结果如 [[1],[1],[1]] 的形式,放置就是将切割下来的块放置到数组容器中。

那要怎样切割呢?

因为指定了大小,因此切割跟切蛋糕很像,参数 size 是尺子,测好每块的长度,slice 函数是刀, 将数组一块一块切出来。

例如有 [1,2,3,4,5] 这个数组,size 指定为 2,则第一次切割会得到 [1,2] 的块,第二次切割得到 [4,5],剩下的是 [5] 。这个数组最终会被切为三块。

明白了原理,下面来看看源码。

源码总览

function chunk(array, size) {
size = Math.max(size, 0)
const length = array == null ? 0 : array.length
if (!length || size < 1) {
return []
}
let index = 0
let resIndex = 0
const result = new Array(Math.ceil(length / size)) while (index < length) {
result[resIndex++] = slice(array, index, (index += size))
}
return result
}

参数处理

size = Math.max(size, 0)
const length = array == null ? 0 : array.length
if (!length || size < 1) {
return []
}

确保 length 存在和 size1 大,如果不满足条件,返回空数组。

在切割之前,需要用尺确定切割的数量。

从上面的原理分析可以看到,切割是不公平的,除了前面的块都是等分外,最后一块可能会比前面的少。

那怎么确定切割的数量呢?学过除法的知道, length/size 即可知道平均分块的数量,如果有余数,则余数是最后那块的长度,需要向上取整。

这在 javascript 中可以用 Math.ceil 函数,它返回的是向上取整后的结果。

看下代码:

const result = new Array(Math.ceil(length / size))

这里创建了一个用来放置所有块的容器 result 。容器的长度刚好与块的数量一致。

let index = 0
let resIndex = 0
while (index < length) {
result[resIndex++] = slice(array, index, (index += size))
}

测量好块的数量后,就要下刀切割啦。每切割下一块,就立马放置到容器 result 中。

resIndex 是放置块的位置,index 是切割的开始位置。

index 与块的数量 length 相等时,表示已经切割完毕,停止切割,最后将结果返回。

参考

  1. lodash源码解析——chunk函数

License

署名-非商业性使用-禁止演绎 4.0 国际 (CC BY-NC-ND 4.0)

作者:对角另一面

我的博客即将同步至腾讯云+社区,邀请大家一同入驻。

最新文章

  1. How to make a not-so-boring speech?
  2. 2016 Multi-University Training Contest 2
  3. Vector3 *2 ,ToString()自动四舍五入
  4. 17. javacript高级程序设计-错误处理与调试
  5. 《JavaScript高级程序设计》
  6. Cocos2d-JS中的文本菜单
  7. CentOS7 mariadb 修改编码
  8. Eclipse launch failed.Binary not found解决方案
  9. EL表达式中的“+-x/”四种运算符和条件,比较运算符等
  10. 【POJ3415】 Common Substrings(后缀数组|SAM)
  11. RSA算法原理(二)
  12. 自动生成proto Js语句
  13. 卷积神经网络的一些经典网络(Lenet,AlexNet,VGG16,ResNet)
  14. Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final)-A-Single Wildcard Pattern Matching
  15. Java并发—synchronized关键字
  16. Web API 跨域请求
  17. div 内 图片 垂直居中
  18. Linux安装MySQL8.0.12之二进制安装
  19. linux第四章笔记
  20. C#编程(四十九)----------队列

热门文章

  1. java笔记04: String的理解与运用
  2. LeetCode 108. Convert Sorted Array to Binary Search Tree (有序数组转化为二叉搜索树)
  3. iOS初学,关于变量加下划线问题
  4. bug:逆向思维的延伸
  5. Quartz.NET的使用(附源码)
  6. CSS3新特性汇总
  7. 在找一份相对完整的Webpack项目配置指南么?这里有
  8. POJ2318 TOYS(叉积判断点与直线的关系+二分)
  9. 2017 多校训练 1002 Balala Power!
  10. Long Long Message(后缀数组)