1,chunk
function slice(array, start, end) {
// 1, 对参数进行处理
let length = array == null ? 0 : array.length
if (!length) {
return []
}
// 1.1 对开始参数进行初步处理
start = start == null ? 0 : start
end = end === undefined ? length : end
// 1.2 对开始参数再次进行负数异常处理
if (start < 0) {
start = -start > length ? 0 : (length + start)
}
// 1.3 对结束参数进行初步处理
end = end > length ? length : end
// 1.4 对结束参数再次进行负数异常处理
if (end < 0) {
end += length
}
//x >>> 0本质上就是保证x有意义(为数字类型),且为正整数,在有效的数组范围内(0 ~ 0xFFFFFFFF)
//,且在无意义的情况下缺省值为0。一个小小的表达式,隐藏着着多重的异常处理。js真是诡异啊。
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
}
function chunk(array, size) {
// size默认值为1
// 如果size小于0,取0处理,大于0,则取size值
size = Math.max(size, 0)
// 如果array为null,length取0,否则取array.length
const length = array == null ? 0 : array.length
// 如果length为0或者size小于1,返回一个空数组
if (!length || size < 1) {
return []
}
let index = 0
let resIndex = 0
// 用数组的长度除以size并向上取整以得到分块的个数,新建一个长度为分块个数的数组result
const result = new Array(Math.ceil(length / size))
// 下面的while循环主要做的事情是遍历array数组,每次截取array中的size个元素并将截取结果添加到result数组中
// while循环中index从0开始,每次增加size大小,直到index大于等于length时跳出循环
// 每次循环时,result数组中的索引resIndex加1
// 在每次循环体中,从array中截取索引为index到(index+size)之间的元素返回一个数组,并将返回结果添加到result数组中
// 截取array元素时使用的方法slice实现可以查看slice对应的源码分析
while (index < length) {
result[resIndex++] = slice(array, index, (index += size))
}
// 返回最终结果result
return result
}
2,compact
// false, null, 0, "", undefined, 和 NaN 都是被认为是“假值”。
// compact去除数组的假值
function compact(array) {
let resIndex = 0
const result = []
// 处理参数异常
if (array == null) {
return result
}
for (const value of array) {
if (value) { // 利用 if() 隐式计算来排除假值
result[resIndex++] = value
}
}
return result
}
export default compact
3,concat
// array (Array): 被连接的数组。
// [values] (...*): 连接的值。
function concat(...rest){
let [array,...values] = rest;
let result = JSON.parse(JSON.stringify(array));
values.forEach(v=>{
if(v instanceof Array ){
v.forEach(i=>{
result = [...result,i]
})
}else{
result = [...result,v]
}
})
return result;
}
export default concat
4,difference
// 参数
// array (Array): 要检查的数组。
// [values] (...Array): 排除的值。
// 返回值
// (Array): 返回一个过滤值后的新数组。
function isObjectLike(value) {
// 是否是一个不为null的对象
return typeof value === 'object' && value !== null
}
function isArrayLike(value) {
// 是否 是一个对象 并且不是函数 并且有长度
return value != null && typeof value !== 'function' && isLength(value.length)
}
function isArrayLikeObject(value) {
// 是否会返回一个有长度的数组
return isObjectLike(value) && isArrayLike(value)
}
function baseDifference(array, values, iteratee, comparator) {
let includes = arrayIncludes
let isCommon = true
const result = []
const valuesLength = values.length
if (!array.length) {
return result
}
if (iteratee) {
values = map(values, (value) => iteratee(value))
}
if (comparator) {
includes = arrayIncludesWith
isCommon = false
}
else if (values.length >= LARGE_ARRAY_SIZE) {
includes = cacheHas
isCommon = false
values = new SetCache(values)
}
outer:
for (let value of array) {
const computed = iteratee == null ? value : iteratee(value)
value = (comparator || value !== 0) ? value : 0
if (isCommon && computed === computed) {
let valuesIndex = valuesLength
while (valuesIndex--) {
if (values[valuesIndex] === computed) {
continue outer
}
}
result.push(value)
}
else if (!includes(values, computed, comparator)) {
result.push(value)
}
}
return result
}
function baseFlatten(array, depth, predicate, isStrict, result) {
predicate || (predicate = isFlattenable)
// result 不存在, 默认为空数组
result || (result = [])
if (array == null) {
return result
}
for (const value of array) {
if (depth > 0 && predicate(value)) {
if (depth > 1) {
// Recursively flatten arrays (susceptible to call stack limits).
baseFlatten(value, depth - 1, predicate, isStrict, result)
} else {
result.push(...value)
}
} else if (!isStrict) {
result[result.length] = value
}
}
return result
}
function difference(array, ...values) {
return isArrayLikeObject(array) // 如果是一个有长度的数组继续程序否则返回 空数组
? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true))
: []
}
export default difference
5. differenceBy
// array (Array): 要检查的数组。
// [values] (...Array): 排除的值。
// [iteratee=_.identity] (Array|Function|Object|string): iteratee 调用每个元素。
// iteratee 会调用一个参数:(value)。(首先使用迭代器分别迭代array 和 values中的每个元素,返回的值作为比较值)。
/**
* Gets the last element of `array`.
*
* @since 0.1.0
* @category Array
* @param {Array} array The array to query.
* @returns {*} Returns the last element of `array`.
* @example
*
* last([1, 2, 3])
* // => 3
*/
function last(array) {
const length = array == null ? 0 : array.length
return length ? array[length - 1] : undefined
}
function differenceBy(array, ...values) {
let iteratee = last(values)
if (isArrayLikeObject(iteratee)) { // 如果是个数组那么 那么赋值 undefined
iteratee = undefined
}
return isArrayLikeObject(array)
? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), iteratee)
: []
}
export default differenceBy
6, differenceWith
// array (Array): 要检查的数组。
// [values] (...Array): 排除的值。
// [comparator] (Function): comparator 调用每个元素。
// 这个方法类似 _.difference ,除了它接受一个 comparator (比较器),它调用比较array,values中的元素。 结果值是从第一数组中选择。comparator 调用参数有两个:(arrVal, othVal)。
// 用于比较处理对象数组
function differenceWith(array, ...values) {
let comparator = last(values)
if (isArrayLikeObject(comparator)) {
comparator = undefined
}
return isArrayLikeObject(array)
? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator)
: []
}
export default differenceWith
7,drop
const INFINITY = 1 / 0
const MAX_INTEGER = 1.7976931348623157e+308
function toFinite(value) {
if (!value) {
return value === 0 ? value : 0
}
value = toNumber(value)
if (value === INFINITY || value === -INFINITY) {
const sign = (value < 0 ? -1 : 1)
return sign * MAX_INTEGER
}
// NaN处理 NaN === NaN 为 false
return value === value ? value : 0
}
function toInteger(value) {
// 合理化数值 做边际处理
const result = toFinite(value)
// 把 小数通过余数的方式取出来
const remainder = result % 1
return remainder ? result - remainder : result
}
function drop(array, n=1) {
const length = array == null ? 0 : array.length
return length
? slice(array, n < 0 ? 0 : toInteger(n), length)
: []
}
export default drop