Lodash學習筆記 - slice函數

百忙之中(閒來無事)想抽點時間好好讀一下源碼,因而就選了Lodash來寫一個系列罷。讀源碼順序就按照loadsh文檔順序來。javascript

文檔地址:中文文檔   英文文檔
源碼地址:gayhubcss


第一個函數是chunk,不過源碼中chunk依賴了slice,因此第一篇文章就從slice開始。java

_.slice(array, [start=0], [end=array.length])

這個函數的做用就是裁剪數組array,從start下標開始,到end下標結束,可是並不包含end,並將結果做爲一個數組返回。而且註明了:git

Note: 這個方法用於代替 Array#slice 來確保數組正確返回。

看起來和原生javascript的slice沒有區別,那爲何要重寫這個函數呢?有如下幾個緣由:github

  1. 比原生slice更快,測試地址,結果如圖:clipboard.png
  2. 有更好的兼容性,IE < 9 時沒法轉化僞數組對象(例如DOM),出處

下面咱們來看一下具體的實現,一行行來看代碼:數組

  • 首先是數組array是否合法的判斷:jsp

    let length = array == null ? 0 : array.length
    if (!length) {
        return []
    }
  • 開始位置start和結束位置end默認值:函數

    start = start == null ? 0 : start
    end = end === undefined ? length : end
  • 支持負數start,以及start合法性檢測:超出數組長度即爲0,不然從右往左數測試

    if (start < 0) {
        start = -start > length ? 0 : (length + start)
    }
  • end合法性檢測:超出數組長度即爲數組長度
    若是end爲負數,則從右往左數spa

    end = end > length ? length : end
    if (end < 0) {
        end += length
    }
  • 數組裁剪後的長度,這裏爲了速度因此使用了>>>來向下取整
    start向下取整

    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

最後貼個源碼:

/**
 * 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. A negative index will be treated as an offset from the end. 
 * @param {number} [end=array.length] The end position. A negative index will be treated as an offset from the end. 
 * @returns {Array} Returns the slice of `array`.
 */
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
}

export default slice

clipboard.png

相關文章
相關標籤/搜索