本文首發於技術風暴-Lodash源碼講解javascript
這是咱們閱讀源碼的第1篇博客,這一篇博客主要介紹Lodash的slice函數,這個函數內部的實現沒有依賴別的函數;咱們這篇博客就來說解一下這個slice函數。html
咱們首先來看一下這個函數的源碼,源碼以下所示:java
/** * 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
首先咱們來講一下這個函數的做用,它的做用就是獲取一個數組的切片;所謂切片,就是指數組的一部分連續元素,固然也能夠是數組的所有元素。咱們這時可能想到了數組自己就有一個slice
方法,那咱們爲何不使用原生的數組的那個slice
方法而非要本身從新寫一個呢?git
有兩個緣由:github
下面咱們就來好好看一下這個函數,首先這個函數須要接收三個參數,可是後兩個參數不是必須選擇的;第一個參數是一個數組,能夠是元素的節點集合;第二個參數表示開始截取切片的位置,第三個參數表示的是切片截取的截至位置,可是不包含這個數所在位置的元素。數組
接下來是分步驟的講解,我在相應的位置作了標記,你們看的時候能夠找標記的位置,下面的講解就是按照標記的位置來的。瀏覽器
#1
:咱們使用了三目運算符來判斷是否傳入了一個數組,若是沒有傳入數組咱們直接把數組的長度設置爲0;反之,咱們就獲取數組的長度;而後作了一個判斷,若是數組的長度爲0,咱們直接返回一個空的數組。#2
:判斷參數start
和end
是否存在;若是都存在的話,就取傳入的這個值;若是不存在的話,start
的取值默認爲0
, end
的取值默認爲數組的長度。#3
:判斷參數start
是不是負數;若是start
是負數的話,再比較一下start
的相反數與數組長度的大小,若是大於數組的長度,那麼就賦值爲0;反之,就把start
賦值爲length + start
,也就是從數組的後面開始數開始截取的位置;而後判斷一下end
是否大於數組的長度,若是大於數組的長度,那麼就把它賦值爲數組的長度;而後判斷一下end
是否小於0
,若是小於0
的話,就賦值爲end + length
,也就是從後向前數結束的位置。#4
:咱們看到>>>
這樣一個操做符,這個是按位移動操做符,表示向右無符號移動
;咱們先來看一下代碼,首先判斷start
是否大於end
,若是大於end
就把length
的值設爲0
,不然就把end
減去start
而後向右無符號移動零位
;而後把start
向右無符號移動零位。那麼這裏爲何要使用>>>
這個按位操做符呢?首先咱們要了解>>>
的做用,>>>
的做用就是把一個數字,變成一個無符號的32位的整數,那麼num >>> 0
的做用,就是把num
變成一個無符號的32位的整數,不論num
是負數仍是小數。並且咱們還須要知道,JavaScript的數組的最大長度是2^32-1
,因此這樣作也避免了數組的索引超出界限。 #5
:上一步計算出了咱們要取的數組的長度,而後咱們在這一步就新建立了一個數組,而後將咱們要獲取的數組的值,從原數組中拷貝過來;而後返回這個數組。到這裏,咱們已經把這個函數須要注意的地方都講解了一下;那麼接下來就須要咱們本身去實現這麼一個函數了,slice是我實現的一個版本。你們能夠去好好練一下啦,沒有什麼特別困難的地方。app
對了,上面咱們說了要比較一下_.slice
和原生的[].slice
方法的性能,下圖是在個人電腦上的一個測試,你們也能夠本身測試測試一下,測試的連接是slice-vs-slicejsp
從上圖能夠明顯的看到,_.slice
方法比原生的[].slice
方法性能要好不少。函數