本文首发于技术风暴-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
方法性能要好不少。函数