zoukankan      html  css  js  c++  java
  • lodash源码分析之chunk的尺与刀

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

    ——莎士比亚《麦克白》

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

    本文为读 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)

    作者:对角另一面
    我的博客即将同步至腾讯云+社区,邀请大家一同入驻。

  • 相关阅读:
    Laravel使用Eloquent ORM操作数据库
    Laravel查询构造器的使用方法整理
    [wordpress]后台自定义菜单字段和使用wordpress color picker
    Thinkphp kindeditor 内容转义
    WordPress 后台提示输入FTP信息
    [记录]gulp compass
    symonfy 项目根目录下没有 bin/console 文件的解决方法
    [gulp] gulp lint 忽略文件
    [转载]ubuntu Atheros Communications Device 1083 驱动
    SharpDevelop 编译时,任务失败,因为未找到“resgen.exe”的解决方法
  • 原文地址:https://www.cnblogs.com/hefty/p/7997485.html
Copyright © 2011-2022 走看看