摘要:本文首发于技术风暴源码讲解这是我们阅读源码的第篇博客,这一篇博客主要介绍的函数,这个函数内部的实现没有依赖别的函数我们这篇博客就来讲解一下这个函数。
本文首发于技术风暴-Lodash源码讲解
这是我们阅读源码的第1篇博客,这一篇博客主要介绍Lodash的slice函数,这个函数内部的实现没有依赖别的函数;我们这篇博客就来讲解一下这个slice函数。
我们首先来看一下这个函数的源码,源码如下所示:
/** * 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方法而非要自己重新写一个呢?
有两个原因:
更好的兼容性,确保了IE浏览器在版本小于9的情况下,对于元素节点列表的操作可以返回一个密集的数组(dense-arrays,这个不太好翻译)
比原生的方法效率更高,这个会在本文的后面有一个对比图。
下面我们就来好好看一下这个函数,首先这个函数需要接收三个参数,但是后两个参数不是必须选择的;第一个参数是一个数组,可以是元素的节点集合;第二个参数表示开始截取切片的位置,第三个参数表示的是切片截取的截至位置,但是不包含这个数所在位置的元素。
接下来是分步骤的讲解,我在相应的位置做了标记,大家看的时候可以找标记的位置,下面的讲解就是按照标记的位置来的。
#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是我实现的一个版本。大家可以去好好练一下啦,没有什么特别困难的地方。
对了,上面我们说了要比较一下_.slice和原生的[].slice方法的性能,下图是在我的电脑上的一个测试,大家也可以自己测试测试一下,测试的链接是slice-vs-slice
从上图可以明显的看到,_.slice方法比原生的[].slice方法性能要好很多。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/91409.html
摘要:原文首发于源码讲解这是我们阅读源码的第篇博客,在这篇文章里我们来学习一下的方法。好啦,关于函数暂时就先讲到这里啦。与恶龙缠斗过久自身亦成为恶龙凝视深渊过久深渊将回以凝视。 原文首发于Lodash源码讲解 这是我们阅读Lodash源码的第2篇博客,在这篇文章里我们来学习一下Lodash的chunk方法。 chunk函数内部依赖其他的函数,依赖的函数如下所示; slice 按照惯例,我们先...
摘要:文档地址中文文档英文文档源码地址第一个函数是,不过源码中依赖了,所以第一篇文章就从开始。这个函数的作用就是裁剪数组,从下标开始,到下标结束,但是并不包含,并将结果作为一个数组返回。并且注明了这个方法用于代替来确保数组正确返回。 百忙之中(闲来无事)想抽点时间好好读一下源码,于是就选了Lodash来写一个系列罢。读源码顺序就按照loadsh文档顺序来。 文档地址:中文文档 英文文档源...
摘要:万条数据依赖读源码之从看稀疏数组与密集数组原理的原理归结起来就是切割和放置。尺在切割之前,需要用尺确定切割的数量。容器的长度刚好与块的数量一致。当与块的数量相等时,表示已经切割完毕,停止切割,最后将结果返回。 以不正义开始的事情,必须用罪恶使它巩固。——莎士比亚《麦克白》 最近很多事似乎印证了这句话,一句谎言最后要用一百句谎言来圆谎。 本文为读 lodash 源码的第二篇,后续文章会...
摘要:文档地址中文文档英文文档源码地址将数组拆分成多个长度的区块,并将这些区块组成一个新数组。如果无法被分割成全部等长的区块,那么最后剩余的元素将组成一个区块。 百忙之中(闲来无事)想抽点时间好好读一下源码,于是就选了Lodash来写一个系列罢。读源码顺序就按照loadsh文档顺序来。 文档地址:中文文档 英文文档源码地址:gayhub _.chunk(array, [size...
摘要:今天回答了的问题生产嵌套数组也就是对数组分组更好的写法。实现像这种,目标数组长度和原数组长度不一致的情况,函数式写法很容易想到函数。小结数组分组是一个很简单的问题,有很多种方法来处理。 今天回答了 @_bleach 的问题:JS生产嵌套数组(也就是对数组分组)更好的写法。回答的过程中对 lodash _.chunk() 产生了好奇,所以分析了一下它的源码,再加上我自己的解决方案,收集...
阅读 3287·2021-11-25 09:43
阅读 1253·2021-11-23 09:51
阅读 3577·2021-10-11 11:06
阅读 3636·2021-08-31 09:41
阅读 3574·2019-08-30 15:53
阅读 3442·2019-08-30 15:53
阅读 941·2019-08-30 15:43
阅读 3278·2019-08-29 14:02