以不正義開始的事情,必須用罪惡使它鞏固。——莎士比亞《麥克白》javascript
最近不少事彷佛印證了這句話,一句謊話最後要用一百句謊話來圓謊。前端
本文爲讀 lodash 源碼的第二篇,後續文章會更新到這個倉庫中,歡迎 star:pocket-lodashjava
gitbook也會同步倉庫的更新,gitbook地址:pocket-lodashnode
chunk
函數能夠將一個數組,切割成指定大小的塊,返回由這些塊組成的新數組。git
chunk
函數在前端能夠用來緩解一些性能問題。例如大量的 DOM 操做,能夠分塊讓瀏覽器在空閒的時候處理,避免頁面卡死。以下面的代碼,向頁面中插入大量的DOM。github
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看稀疏數組與密集數組segmentfault
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
存在和 size
比 1
大,若是不知足條件,返回空數組。
在切割以前,須要用尺肯定切割的數量。
從上面的原理分析能夠看到,切割是不公平的,除了前面的塊都是等分外,最後一塊可能會比前面的少。
那怎麼肯定切割的數量呢?學過除法的知道, 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
相等時,表示已經切割完畢,中止切割,最後將結果返回。
署名-非商業性使用-禁止演繹 4.0 國際 (CC BY-NC-ND 4.0)
最後,全部文章都會同步發送到微信公衆號上,歡迎關注,歡迎提意見:
做者:對角另外一面