每天一个Lodash源码解析
- chunk()
- 方法介绍
- 自我实现
- 源码分析
- 代码对比
- 知识点补充
- 浮点数转化为浮点数
- 数组创建方法区别
- js中切割数组方法
- slice()
-
- compact()
-
chunk()
方法介绍
_.chunk(array, [size=1])
将数组(array)拆分成多个 size 长度的区块,并将这些区块组成一个新数组。 如果array 无法被分割成全部等长的区块,那么最后剩余的元素将组成一个区块。
参数
- array (Array): 需要处理的数组
- [size=1] (number): 每个数组区块的长度
返回
- (Array): 返回一个包含拆分区块的新数组(注:相当于一个二维数组)。
例子
_.chunk(['a', 'b', 'c', 'd'], 2);
_.chunk(['a', 'b', 'c', 'd'], 3);
自我实现
var chunk = function(arr, size) {
var l = arr.length
if (size == undefined) size = 1
var newA = []
var indexf = 0
var indexe = size
if (size == 0) {
newA = []
return newA;
}
while (l > size) {
var a = arr.slice(indexf, indexe)
l = l - size
indexf = indexf + size
indexe = indexe + size
newA.push(a)
}
if (l > 0) {
indexf = indexe - size
indexe = arr.length
var a = arr.slice(indexf, indexe)
newA.push(a)
}
return newA;
}
源码分析
function chunk(array, size = 1) {
size = Math.max(toInteger(size), 0)
const length = array == null ? 0 : array.length
if (!length || size < 1) {
return []
}
let index = 0
let resIndex = 0
const result = new Array(Math.ceil(length / size))
while (index < length) {
result[resIndex++] = slice(array, index, (index += size))
}
return result
}
代码对比
- 源码相对来说,减少了很多声明,并少了很多冗余的代码,且具有很好的可读性
- 对于数组接收到的值有很好的判断并处理
知识点补充
浮点数转化为浮点数
使用Math中的方法
- Math.floor():保留整数
- Math.ceil():向上取整
- Math.round():四舍五入
使用|
(位或运算符)将浮点数截断为整数。
console.log(23.9 | 0);
console.log(-23.9 | 0);
数组创建方法区别
使用new Array
创建的数组,具有length
属性,没有每个元素。
使用Array.from
创建的数组,具有length
属性,每个元素为undefined
,因此后续可以使用filter或者map等方法。
array.from
还可以转为类似数组的对象,...
扩展运算符不能。
console.log(new Array(2))
console.log(Array.from({
length: 2
}))
let arr = [1, 2]
console.log(arr)
console.log([...arr])
运行结果
js中切割数组方法
slice()
返回一个索引和另一个索引之间的数据(不改变原数组),
slice(start,end)有两个参数(start必需,end选填),都是索引,返回值不包括end
splice()
用来添加或者删除数组的数据,只返回被删除的数据,类型为数组(改变原数组)
slice()
方法介绍
_.slice(array, [start=0], [end=array.length])
裁剪数组array,从 start 位置开始到end结束,但不包括 end 本身的位置。
Note: 这个方法用于代替Array#slice 来确保数组正确返回。
参数
- array (Array): 要裁剪数组。
- [start=0] (number): 开始位置。
- [end=array.length] (number): 结束位置。
返回
- (Array): 返回 数组array 裁剪部分的新数组。
PS:
- start 必需。规定从何处开始选取。如果是负数,那么它规定从数组尾部开始算起的位置。也就是说,-1 指最后一个元素,-2 指倒数第二个元素,以此类推。
- end 可选。规定从何处结束选取。该参数是数组片断结束处的数组下标。如果没有指定该参数,那么切分的数组包含从 start 到数组结束的所有元素。如果这个参数是负数,那么它规定的是从数组尾部开始算起的元素。
自我实现
var slice = function(array, start, end) {
let a = []
for (var i = start; i < end; i++) {
console.log(i)
a.push(array[i])
}
return a
}
源码分析
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
}
代码对比
- 相较于自我实现,对于传递过来的参数的的错误判断更为具体与正确
- 循环变量采用代码直接编写,没有调用方法,加快速度
知识点补充
>>>
移位运算
x >>> 0本质上就是保证x有意义(为数字类型),且为正整数,在有效的数组范围内(0 ~ 0xFFFFFFFF),且在无意义的情况下缺省值为0。
具体参考:https://segmentfault.com/a/1190000014613703
compact()
方法介绍
创建一个新数组,包含原数组中所有的非假值元素。例如false
, null
,0
," "
, undefined
, 和 NaN
都是被认为是“假值”。
参数
返回
自我实现
var compact = function(array) {
if (array.length == 0) return []
var newaArray = []
for (let i = 0; i < array.length; i++) {
var type = Object.prototype.toString.call(array[i])
if (type == '[object Null]' || type == '[object Undefined]') {
continue;
} else if (type == '[object Number]') {
if (array[i] == 0 || isNaN(array[i])) continue;
else newaArray.push(array[i])
} else if (type == '[object Boolean]') {
if (array[i] == false) continue;
else newaArray.push(array[i])
} else if (type == '[object String]') {
if (array[i] == "") continue;
else newaArray.push(array[i])
} else {
newaArray.push(array[i])
}
}
return newaArray
}
源码分析
function compact(array) {
let resIndex = 0
const result = []
if (array == null) {
return result
}
遍历array数组,将数组中的每个元素转化为布尔值后判断是否为ture,false为虚假值,需要过滤
for (const value of array) {
if (value) {
result[resIndex++] = value
}
}
return result
}
代码对比
- 相较于自我实现,源码的代码简洁明了,通过转化为布尔类型省略了很多判断
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)