成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

讀lodash源碼之從slice看稀疏數(shù)組與密集數(shù)組

lijy91 / 2083人閱讀

摘要:例如其中的為,但是數(shù)組中沒有元素,是稀疏數(shù)組而每個(gè)位置都是有元素的,雖然每個(gè)元素都為,為密集數(shù)組。那稀疏數(shù)組和密集數(shù)組有什么區(qū)別呢在中最主要考慮的是兩者在迭代器中的表現(xiàn)。截取并返回新數(shù)組為新數(shù)組容器。

卑鄙是卑鄙者的通行證,高尚是高尚者的墓志銘。

——北島《回答》

看北島就是從這兩句詩(shī)開始的,高尚者已死,只剩卑鄙者在世間橫行。

本文為讀 lodash 源碼的第一篇,后續(xù)文章會(huì)更新到這個(gè)倉(cāng)庫(kù)中,歡迎 star:pocket-lodash

gitbook也會(huì)同步倉(cāng)庫(kù)的更新,gitbook地址:pocket-lodash

引言

你可能會(huì)有點(diǎn)奇怪,原生的 slice 方法基本沒有兼容性的問題,為什么 lodash 還要實(shí)現(xiàn)一個(gè) slice 方法呢?

這個(gè)問題,lodash 的作者已經(jīng)在 why not the "baseslice" func use Array.slice(), loop faster than slice? 的 issue 中給出了答案:lodash 的 slice 會(huì)將數(shù)組當(dāng)成密集數(shù)組對(duì)待,原生的 slice 會(huì)將數(shù)組當(dāng)成稀疏數(shù)組對(duì)待。

密集數(shù)組VS稀疏數(shù)組

我們先來看看犀牛書是怎樣定義稀疏數(shù)組的:

稀疏數(shù)組就是包含從0開始的不連續(xù)索引的數(shù)組。通常,數(shù)組的length屬性值代表數(shù)組中元素的個(gè)數(shù)。如果數(shù)組是稀疏的,length屬性值大于元素的個(gè)數(shù)。

如果數(shù)組是稀疏的,那么這個(gè)數(shù)組中至少有一個(gè)以上的位置不存在元素(包括 undefined )。

例如:

var sparse = new Array(10)
var dense = new Array(10).fill(undefined)

其中 sparselength 為10,但是 sparse 數(shù)組中沒有元素,是稀疏數(shù)組;而 dense 每個(gè)位置都是有元素的,雖然每個(gè)元素都為undefined,為密集數(shù)組 。

那稀疏數(shù)組和密集數(shù)組有什么區(qū)別呢?在 lodash 中最主要考慮的是兩者在迭代器中的表現(xiàn)。

稀疏數(shù)組在迭代的時(shí)候會(huì)跳過不存在的元素。

sparse.forEach(function(item){
  console.log(item)
})
dense.forEach(function(item){
  console.log(item)
})

sparse 根本不會(huì)調(diào)用 console.log 打印任何東西,但是 dense 會(huì)打印出10個(gè) undefined 。

源碼總覽

當(dāng)然,除了對(duì)待稀疏數(shù)組跟原生的 slice 不一致外,其他的規(guī)則還是一樣的,下面是 lodash 實(shí)現(xiàn) slice 的源碼。

function slice(array, start, end) {
  let length = array == null ? 0 : array.length
  if (!length) {
    return []
  }
  start = start == null ? 0 : start
  end = end === undefined ? length : end

  if (start < 0) {
    start = -start > length ? 0 : (length + start)
  }
  end = end > length ? length : end
  if (end < 0) {
    end += length
  }
  length = start > end ? 0 : ((end - start) >>> 0)
  start >>>= 0

  let index = -1
  const result = new Array(length)
  while (++index < length) {
    result[index] = array[index + start]
  }
  return result
}
不傳參的情況
let length = array == null ? 0 : array.length
if (!length) {
  return []
}

不傳參時(shí),length 默認(rèn)為0,否則獲取數(shù)組的長(zhǎng)度。注意這里用的是 array == null ,非 array === null ,包含了 undefined 的判斷。

所以在不傳參調(diào)用 lodash 的 slice 時(shí),返回的是空數(shù)組,而原生的 slice 沒有這種調(diào)用方式。

處理start參數(shù)

start 參數(shù)用來指定截取的開始位置。

先來看下 MDN 對(duì)該參數(shù)的描述:

如果該參數(shù)為負(fù)數(shù),則表示從原數(shù)組中的倒數(shù)第幾個(gè)元素開始提取。

如果省略,則從索引0開始

start = start == null ? 0 : start

因此這段是處理省略的情況,省略時(shí),默認(rèn)值為0。

if (start < 0) {
  start = -start > length ? 0 : (length + start)
}

這段是處理負(fù)數(shù)的情況。

如果負(fù)數(shù)取反后比數(shù)組的長(zhǎng)度還要大,即超出了數(shù)組的范圍,則取值為0,表示從開始的位置截取,否則用 length + start ,即向后倒數(shù)。

start >>>= 0

最后,用在 >>> 來確保 start 參數(shù)為整數(shù)或0。

因?yàn)?lodash 的 slice 除了可以處理數(shù)組外,也可以處理類數(shù)組,因此第一個(gè)參數(shù) array 可能為一個(gè)對(duì)象, length 屬性不一定為數(shù)字。

處理end參數(shù)

end 參數(shù)用來指定截取的結(jié)束位置。

同樣來看下 MDN 對(duì)些的描述:

如果該參數(shù)為負(fù)數(shù),則它表示在原數(shù)組中的倒數(shù)第幾個(gè)元素結(jié)束制取。

如果end被省略,則slice會(huì)一直提取到原數(shù)組的末尾。

如果end大于數(shù)組長(zhǎng)度,slice也會(huì)一直提取到原數(shù)組末尾。

end = end === undefined ? length : end

這段是處理 end 被省略的情況,省略時(shí),end 默認(rèn)為為 length,即截取到數(shù)組的末尾。

end = end > length ? length : end

這是處理 end 比數(shù)組長(zhǎng)度大的情況,如果被數(shù)組長(zhǎng)度大,也會(huì)截取到數(shù)組的末尾。

if (end < 0) {
  end += length
}

這段是處理負(fù)值的情況,如果為負(fù)值,則從數(shù)組末尾開始向前倒數(shù)。

這里沒有像 start 一樣控制 end 的向前倒數(shù)完后是否為負(fù)數(shù),因?yàn)楹竺孢€有一層控制。

獲取新數(shù)組的長(zhǎng)度
length = start > end ? 0 : ((end - start) >>> 0)

新數(shù)組的長(zhǎng)度計(jì)算方式很簡(jiǎn)單,就是用 edn - start 即可得出。

上面說到,沒有控制最終 end 是否為負(fù)數(shù)的情況。這里用的是 startend 的比較,如果 startend 大,則新數(shù)組長(zhǎng)度為0,即返回一個(gè)空數(shù)組。否則用 end - start 來計(jì)算。

這里同樣用了無符號(hào)右移位運(yùn)算符來確保 length 為正數(shù)或0。

截取并返回新數(shù)組
let index = -1
const result = new Array(length)
while (++index < length) {
  result[index] = array[index + start]
}
return result

result 為新數(shù)組容器。

while 循環(huán),從 start 位置開始,獲取原數(shù)組的值,依次存入新的數(shù)組中。

因?yàn)槭峭ㄟ^索引取值,如果遇到稀疏數(shù)組,對(duì)應(yīng)的索引值上沒有元素時(shí),通過數(shù)組索引取值返回的是 undefined, 但這并不是說稀疏數(shù)組中該位置的值為 undefined

最后將 result 返回。

參考

javascript權(quán)威指南(第6版), David Flanagan著,淘寶前端團(tuán)隊(duì)譯,機(jī)械工業(yè)出版社

why not the "baseslice" func use Array.slice(), loop faster than slice?

Array.prototype.slice()

JavaScript: sparse arrays vs. dense arrays

【譯】JavaScript中的稀疏數(shù)組與密集數(shù)組

License

署名-非商業(yè)性使用-禁止演繹 4.0 國(guó)際 (CC BY-NC-ND 4.0)

最后,所有文章都會(huì)同步發(fā)送到微信公眾號(hào)上,歡迎關(guān)注,歡迎提意見:

作者:對(duì)角另一面

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/89896.html

相關(guān)文章

  • lodash源碼分析之chunk的尺

    摘要:萬條數(shù)據(jù)依賴讀源碼之從看稀疏數(shù)組與密集數(shù)組原理的原理歸結(jié)起來就是切割和放置。尺在切割之前,需要用尺確定切割的數(shù)量。容器的長(zhǎng)度剛好與塊的數(shù)量一致。當(dāng)與塊的數(shù)量相等時(shí),表示已經(jīng)切割完畢,停止切割,最后將結(jié)果返回。 以不正義開始的事情,必須用罪惡使它鞏固?!勘葋啞尔溈税住? 最近很多事似乎印證了這句話,一句謊言最后要用一百句謊言來圓謊。 本文為讀 lodash 源碼的第二篇,后續(xù)文章會(huì)...

    ZweiZhao 評(píng)論0 收藏0
  • Lodash源碼講解-slice函數(shù)

    摘要:本文首發(fā)于技術(shù)風(fēng)暴源碼講解這是我們閱讀源碼的第篇博客,這一篇博客主要介紹的函數(shù),這個(gè)函數(shù)內(nèi)部的實(shí)現(xiàn)沒有依賴別的函數(shù)我們這篇博客就來講解一下這個(gè)函數(shù)。 本文首發(fā)于技術(shù)風(fēng)暴-Lodash源碼講解 這是我們閱讀源碼的第1篇博客,這一篇博客主要介紹Lodash的slice函數(shù),這個(gè)函數(shù)內(nèi)部的實(shí)現(xiàn)沒有依賴別的函數(shù);我們這篇博客就來講解一下這個(gè)slice函數(shù)。 我們首先來看一下這個(gè)函數(shù)的源碼,源碼...

    李義 評(píng)論0 收藏0
  • 《javascript高級(jí)程序設(shè)計(jì)》筆記_數(shù)組 稀疏數(shù)組數(shù)組

    摘要:數(shù)組是數(shù)據(jù)的有序列表,與其他語言不同的是,數(shù)組的每一項(xiàng)可以保存任何類型的數(shù)據(jù)。如下的代碼創(chuàng)建的就是一個(gè)密集數(shù)組稀疏數(shù)組與密集數(shù)組相反,并不強(qiáng)制要求數(shù)組元素是緊密相連的,即允許間隙的存在。 數(shù)組是數(shù)據(jù)的有序列表,與其他語言不同的是,ECMAScript 數(shù)組的每一項(xiàng)可以保存任何類型的數(shù)據(jù)。也就是說,可以用數(shù)組的第一個(gè)位置來保存字符串,用第二位置來保存數(shù)值,用第三個(gè)位置來保存對(duì)象, 以此類...

    pepperwang 評(píng)論0 收藏0
  • Lodash學(xué)習(xí)筆記 - slice函數(shù)

    摘要:文檔地址中文文檔英文文檔源碼地址第一個(gè)函數(shù)是,不過源碼中依賴了,所以第一篇文章就從開始。這個(gè)函數(shù)的作用就是裁剪數(shù)組,從下標(biāo)開始,到下標(biāo)結(jié)束,但是并不包含,并將結(jié)果作為一個(gè)數(shù)組返回。并且注明了這個(gè)方法用于代替來確保數(shù)組正確返回。 百忙之中(閑來無事)想抽點(diǎn)時(shí)間好好讀一下源碼,于是就選了Lodash來寫一個(gè)系列罷。讀源碼順序就按照loadsh文檔順序來。 文檔地址:中文文檔?? 英文文檔源...

    lei___ 評(píng)論0 收藏0
  • Lodash學(xué)習(xí)筆記 - chunk函數(shù)

    摘要:文檔地址中文文檔英文文檔源碼地址將數(shù)組拆分成多個(gè)長(zhǎng)度的區(qū)塊,并將這些區(qū)塊組成一個(gè)新數(shù)組。如果無法被分割成全部等長(zhǎng)的區(qū)塊,那么最后剩余的元素將組成一個(gè)區(qū)塊。 百忙之中(閑來無事)想抽點(diǎn)時(shí)間好好讀一下源碼,于是就選了Lodash來寫一個(gè)系列罷。讀源碼順序就按照loadsh文檔順序來。 文檔地址:中文文檔?? 英文文檔源碼地址:gayhub _.chunk(array, [size...

    DrizzleX 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<