摘要:本文首發(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ù)的源碼,源碼如下所示:
/** * Creates a slice of `array` from `start` up to, but not including, `end`. * * **Note:** This method is used instead of * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are * returned. * * @since 3.0.0 * @category Array * @param {Array} array The array to slice. * @param {number} [start=0] The start position. * @param {number} [end=array.length] The end position. * @returns {Array} Returns the slice of `array`. */ function slice(array, start, end) { // #1 let length = array == null ? 0 : array.length if (!length) { return [] } // #2 start = start == null ? 0 : start end = end === undefined ? length : end // #3 if (start < 0) { start = -start > length ? 0 : (length + start) } end = end > length ? length : end if (end < 0) { end += length } // #4 length = start > end ? 0 : ((end - start) >>> 0) start >>>= 0 // #5 let index = -1 const result = new Array(length) while (++index < length) { result[index] = array[index + start] } return result } export default slice
首先我們來說一下這個(gè)函數(shù)的作用,它的作用就是獲取一個(gè)數(shù)組的切片;所謂切片,就是指數(shù)組的一部分連續(xù)元素,當(dāng)然也可以是數(shù)組的全部元素。我們這時(shí)可能想到了數(shù)組本身就有一個(gè)slice方法,那我們?yōu)槭裁床皇褂迷臄?shù)組的那個(gè)slice方法而非要自己重新寫一個(gè)呢?
有兩個(gè)原因:
更好的兼容性,確保了IE瀏覽器在版本小于9的情況下,對(duì)于元素節(jié)點(diǎn)列表的操作可以返回一個(gè)密集的數(shù)組(dense-arrays,這個(gè)不太好翻譯)
比原生的方法效率更高,這個(gè)會(huì)在本文的后面有一個(gè)對(duì)比圖。
下面我們就來好好看一下這個(gè)函數(shù),首先這個(gè)函數(shù)需要接收三個(gè)參數(shù),但是后兩個(gè)參數(shù)不是必須選擇的;第一個(gè)參數(shù)是一個(gè)數(shù)組,可以是元素的節(jié)點(diǎn)集合;第二個(gè)參數(shù)表示開始截取切片的位置,第三個(gè)參數(shù)表示的是切片截取的截至位置,但是不包含這個(gè)數(shù)所在位置的元素。
接下來是分步驟的講解,我在相應(yīng)的位置做了標(biāo)記,大家看的時(shí)候可以找標(biāo)記的位置,下面的講解就是按照標(biāo)記的位置來的。
#1:我們使用了三目運(yùn)算符來判斷是否傳入了一個(gè)數(shù)組,如果沒有傳入數(shù)組我們直接把數(shù)組的長度設(shè)置為0;反之,我們就獲取數(shù)組的長度;然后做了一個(gè)判斷,如果數(shù)組的長度為0,我們直接返回一個(gè)空的數(shù)組。
#2:判斷參數(shù)start和end是否存在;如果都存在的話,就取傳入的這個(gè)值;如果不存在的話,start的取值默認(rèn)為0, end的取值默認(rèn)為數(shù)組的長度。
#3:判斷參數(shù)start是否是負(fù)數(shù);如果start是負(fù)數(shù)的話,再比較一下start的相反數(shù)與數(shù)組長度的大小,如果大于數(shù)組的長度,那么就賦值為0;反之,就把start賦值為length + start,也就是從數(shù)組的后面開始數(shù)開始截取的位置;然后判斷一下end是否大于數(shù)組的長度,如果大于數(shù)組的長度,那么就把它賦值為數(shù)組的長度;然后判斷一下end是否小于0,如果小于0的話,就賦值為end + length,也就是從后向前數(shù)結(jié)束的位置。
#4:我們看到>>>這樣一個(gè)操作符,這個(gè)是按位移動(dòng)操作符,表示向右無符號(hào)移動(dòng);我們先來看一下代碼,首先判斷start是否大于end,如果大于end就把length的值設(shè)為0,否則就把end減去start然后向右無符號(hào)移動(dòng)零位;然后把start向右無符號(hào)移動(dòng)零位。那么這里為什么要使用>>>這個(gè)按位操作符呢?首先我們要了解>>>的作用,>>>的作用就是把一個(gè)數(shù)字,變成一個(gè)無符號(hào)的32位的整數(shù),那么num >>> 0的作用,就是把num變成一個(gè)無符號(hào)的32位的整數(shù),不論num是負(fù)數(shù)還是小數(shù)。而且我們還需要知道,JavaScript的數(shù)組的最大長度是2^32-1,所以這樣做也避免了數(shù)組的索引超出界限。
#5:上一步計(jì)算出了我們要取的數(shù)組的長度,然后我們?cè)谶@一步就新創(chuàng)建了一個(gè)數(shù)組,然后將我們要獲取的數(shù)組的值,從原數(shù)組中拷貝過來;然后返回這個(gè)數(shù)組。
到這里,我們已經(jīng)把這個(gè)函數(shù)需要注意的地方都講解了一下;那么接下來就需要我們自己去實(shí)現(xiàn)這么一個(gè)函數(shù)了,slice是我實(shí)現(xiàn)的一個(gè)版本。大家可以去好好練一下啦,沒有什么特別困難的地方。
對(duì)了,上面我們說了要比較一下_.slice和原生的[].slice方法的性能,下圖是在我的電腦上的一個(gè)測(cè)試,大家也可以自己測(cè)試測(cè)試一下,測(cè)試的鏈接是slice-vs-slice
從上圖可以明顯的看到,_.slice方法比原生的[].slice方法性能要好很多。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/91409.html
摘要:原文首發(fā)于源碼講解這是我們閱讀源碼的第篇博客,在這篇文章里我們來學(xué)習(xí)一下的方法。好啦,關(guān)于函數(shù)暫時(shí)就先講到這里啦。與惡龍纏斗過久自身亦成為惡龍凝視深淵過久深淵將回以凝視。 原文首發(fā)于Lodash源碼講解 這是我們閱讀Lodash源碼的第2篇博客,在這篇文章里我們來學(xué)習(xí)一下Lodash的chunk方法。 chunk函數(shù)內(nèi)部依賴其他的函數(shù),依賴的函數(shù)如下所示; slice 按照慣例,我們先...
摘要:文檔地址中文文檔英文文檔源碼地址第一個(gè)函數(shù)是,不過源碼中依賴了,所以第一篇文章就從開始。這個(gè)函數(shù)的作用就是裁剪數(shù)組,從下標(biāo)開始,到下標(biāo)結(jié)束,但是并不包含,并將結(jié)果作為一個(gè)數(shù)組返回。并且注明了這個(gè)方法用于代替來確保數(shù)組正確返回。 百忙之中(閑來無事)想抽點(diǎn)時(shí)間好好讀一下源碼,于是就選了Lodash來寫一個(gè)系列罷。讀源碼順序就按照loadsh文檔順序來。 文檔地址:中文文檔?? 英文文檔源...
摘要:萬條數(shù)據(jù)依賴讀源碼之從看稀疏數(shù)組與密集數(shù)組原理的原理歸結(jié)起來就是切割和放置。尺在切割之前,需要用尺確定切割的數(shù)量。容器的長度剛好與塊的數(shù)量一致。當(dāng)與塊的數(shù)量相等時(shí),表示已經(jīng)切割完畢,停止切割,最后將結(jié)果返回。 以不正義開始的事情,必須用罪惡使它鞏固?!勘葋啞尔溈税住? 最近很多事似乎印證了這句話,一句謊言最后要用一百句謊言來圓謊。 本文為讀 lodash 源碼的第二篇,后續(xù)文章會(huì)...
摘要:文檔地址中文文檔英文文檔源碼地址將數(shù)組拆分成多個(gè)長度的區(qū)塊,并將這些區(qū)塊組成一個(gè)新數(shù)組。如果無法被分割成全部等長的區(qū)塊,那么最后剩余的元素將組成一個(gè)區(qū)塊。 百忙之中(閑來無事)想抽點(diǎn)時(shí)間好好讀一下源碼,于是就選了Lodash來寫一個(gè)系列罷。讀源碼順序就按照loadsh文檔順序來。 文檔地址:中文文檔?? 英文文檔源碼地址:gayhub _.chunk(array, [size...
摘要:今天回答了的問題生產(chǎn)嵌套數(shù)組也就是對(duì)數(shù)組分組更好的寫法。實(shí)現(xiàn)像這種,目標(biāo)數(shù)組長度和原數(shù)組長度不一致的情況,函數(shù)式寫法很容易想到函數(shù)。小結(jié)數(shù)組分組是一個(gè)很簡單的問題,有很多種方法來處理。 今天回答了 @_bleach 的問題:JS生產(chǎn)嵌套數(shù)組(也就是對(duì)數(shù)組分組)更好的寫法。回答的過程中對(duì) lodash _.chunk() 產(chǎn)生了好奇,所以分析了一下它的源碼,再加上我自己的解決方案,收集...
閱讀 3330·2021-11-25 09:43
閱讀 1314·2021-11-23 09:51
閱讀 3617·2021-10-11 11:06
閱讀 3729·2021-08-31 09:41
閱讀 3607·2019-08-30 15:53
閱讀 3517·2019-08-30 15:53
閱讀 974·2019-08-30 15:43
閱讀 3317·2019-08-29 14:02