lodash源码学习-数组篇

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值