百忙之中(闲来无事)想抽点时间好好读一下源码,于是就选了Lodash来写一个系列罢。读源码顺序就按照loadsh文档顺序来。
第一个函数是chunk
,不过源码中chunk
依赖了slice
,所以第一篇文章就从slice
开始。
_.slice(array, [start=0], [end=array.length])
这个函数的作用就是裁剪数组array,从start下标开始,到end下标结束,但是并不包含end,并将结果作为一个数组返回。并且注明了:
Note: 这个方法用于代替 Array#slice 来确保数组正确返回。
看起来和原生javascript的slice没有区别,那为什么要重写这个函数呢?有以下几个原因:
下面我们来看一下具体的实现,一行行来看代码:
-
首先是数组array是否合法的判断:
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
为负数,则从右往左数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
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。