lodash原始碼分析之chunk的尺與刀

對角發表於2017-12-07

以不正義開始的事情,必須用罪惡使它鞏固。

——莎士比亞《麥克白》

最近很多事似乎印證了這句話,一句謊言最後要用一百句謊言來圓謊。

本文為讀 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)

最後,所有文章都會同步傳送到微信公眾號上,歡迎關注,歡迎提意見:

lodash原始碼分析之chunk的尺與刀

作者:對角另一面

相關文章