每日原始碼分析 – lodash(slice.js)

Canace22發表於2019-02-22

本系列使用 lodash 4.17.4版本

一、原始碼示例


/**
 * 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) {
  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
}

var ret = slice([`1`,`2`,`3`,`4`],1,3)

console.log(ret)
複製程式碼

二、函式作用


上述示例程式碼的結果是:

[ `2`, `3` ]
[Finished in 1.0s]
複製程式碼

大家從結果可以看出來,這個函式跟js裡封裝的slice函式是一樣的作用,slice(array, star, end),通過傳入一個陣列,從陣列中指定一個開始位置,一個結束位置作為索引,深拷貝陣列的一部分到新的陣列,通常用來擷取陣列的子陣列。

三、函式工作原理


  1. 判斷引數合法性。

(1)判斷陣列是否為空:

let length = array == null ? 0 : array.length
if (!length) {
    return []
  }
複製程式碼

(2)判斷引數start的合法性:
* 判斷引數 start 是否為空,若為空,則取0;
* 如果 start > 0,按正序取陣列片段,若 start < 0,則從右到左算起;

start = start == null ? 0 : start
if (start < 0) {
    start = -start > length ? 0 : (length + start)
}
複製程式碼

(3)判斷引數 end 的合法性:
* 判斷引數 end 是否為空,若為空,則取length;
* 判斷引數 end 是否超出陣列長度,若超出,則取 length;
* 如果 end > 0,按正序取陣列片段,若 end < 0,則從右到左算起;

end = end === undefined ? length : end
end = end > length ? length : end
if (end < 0) {
    end += length
}
複製程式碼

(4)判斷引數 start 和 end 的邏輯合法性:
* 若end 大於等於 start,則 length 取(end – start),即新陣列長度;否則,length = 0,返回空陣列;
* 將引數 start 和 end 轉換為十進位制數;

length = start > end ? 0 : ((end - start) >>> 0)
start >>>= 0
複製程式碼
  1. 擷取新陣列,返回結果。

(1)建立一個新陣列 result,長度為length;

(2)讀取陣列 array 中位置為 start 到 end 的元素,存到新陣列 result 中;

(3)返回新陣列 result;

let index = -1
const result = new Array(length)
while (++index < length) {
    result[index] = array[index + start]
}
return result
複製程式碼

本文章來源於午安煎餅計劃Web組 – 初見

相關連結:

每日原始碼分析-Lodash(castArray.js)

每日原始碼分析-Lodash(after.js)

每日原始碼分析-Lodash(chunk.js

相關文章