Lodash源码阅读-concat

Lodash 源码阅读-concat

概述

concat 是 Lodash 的一个数组函数,用来合并数组。它的作用很简单:把一个数组和其他数组或值连接起来,生成一个新数组。这个函数模仿了 JavaScript 原生的 Array.prototype.concat(),但做了一些优化,让使用更方便。

前置学习

依赖函数

  • arrayPush:把一个数组的内容添加到另一个数组末尾
  • baseFlatten:把嵌套数组展平到指定深度
  • copyArray:复制一个数组的内容到新数组
  • isArray:检查一个值是否为数组

技术知识

  • arguments 对象:函数内部用来获取所有参数的特殊对象
  • 浅拷贝:复制对象的直接引用,而不是深层内容
  • 条件判断:根据不同情况执行不同代码
  • 循环 :使用 while 循环遍历参数

源码实现

javascript 复制代码
/**
 * Creates a new array concatenating `array` with any additional arrays
 * and/or values.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Array
 * @param {Array} array The array to concatenate.
 * @param {...*} [values] The values to concatenate.
 * @returns {Array} Returns the new concatenated array.
 * @example
 *
 * var array = [1];
 * var other = _.concat(array, 2, [3], [[4]]);
 *
 * console.log(other);
 * // => [1, 2, 3, [4]]
 *
 * console.log(array);
 * // => [1]
 */
function concat() {
  var length = arguments.length;
  if (!length) {
    return [];
  }
  var args = Array(length - 1),
    array = arguments[0],
    index = length;

  while (index--) {
    args[index - 1] = arguments[index];
  }
  return arrayPush(
    isArray(array) ? copyArray(array) : [array],
    baseFlatten(args, 1)
  );
}

实现思路

concat 函数的实现思路很直接:

  1. 检查是否有参数,没有就返回空数组
  2. 第一个参数当作基础数组
  3. 把剩余参数收集起来
  4. 基础数组是真数组就复制一份,不是就把它包装成数组
  5. 对剩余参数进行一级扁平化处理
  6. 把扁平化后的参数追加到基础数组的副本中
  7. 返回最终合并的结果

这样既保证了原数组不变,又能正确处理各种类型的参数(数组、单个值等)。

源码解析

参数检查

javascript 复制代码
var length = arguments.length;
if (!length) {
  return [];
}

这段先检查传入的参数数量。如果没有参数(length 为 0),就直接返回空数组 []。这是防错处理,确保函数不会出错。

参数处理

javascript 复制代码
var args = Array(length - 1),
  array = arguments[0],
  index = length;

while (index--) {
  args[index - 1] = arguments[index];
}

这段代码做了三件事:

  1. 创建一个新数组 args 用来存放除第一个参数外的所有参数
  2. 把第一个参数存为 array 变量
  3. while 循环从后往前,把第二个到最后一个参数收集到 args 数组中

为什么从后往前循环?这样写比较简洁,可以减少一个循环变量。

数组合并

javascript 复制代码
return arrayPush(
  isArray(array) ? copyArray(array) : [array],
  baseFlatten(args, 1)
);

这段代码是核心:

  1. 先看 array 是不是数组
    • 是数组:复制一份,防止修改原数组
    • 不是数组:包装成数组,如 3 变成 [3]
  2. 对剩余参数 args 进行一级扁平化,比如 [[1], 2] 变成 [1, 2]
  3. arrayPush 把扁平化的结果添加到处理过的基础数组中
  4. 返回最终结果

"一级扁平化"是什么意思?就是只展开一层嵌套,比如:

  • [1, [2, [3]]] 会变成 [1, 2, [3]]
  • 里面的 [3] 不会再被展开

总结

concat 函数虽然简单,但体现了几个重要的编程思想:

  1. 不修改原数据

    • 通过复制原数组来保证原数据不变
    • 这种做法让函数更安全,减少意外错误
  2. 灵活处理不同类型

    • 支持数组、单个值、混合类型作为参数
    • 通过类型检查和适当转换,让 API 使用更方便
  3. 一致的行为

    • 行为与原生 Array.prototype.concat 保持一致
    • 一级扁平化,不会过度展开嵌套数组
  4. 组合式实现

    • 通过组合多个小函数完成功能
    • 每个函数专注做好一件事,代码更清晰易维护
相关推荐
油丶酸萝卜别吃4 分钟前
java中的List集合去重
javascript·vue.js·react.js
Enti7c36 分钟前
css定位
前端·css
Thanks_ks1 小时前
探秘 Ruby 与 JavaScript:动态语言的多面风采
javascript·ruby·应用场景·动态语言·语法特性·开发体验·任务管理系统
勘察加熊人1 小时前
vue自定义颜色选择器
javascript·vue.js·ecmascript
zy0101011 小时前
useEffect
开发语言·前端·javascript·react·useeffect
@PHARAOH1 小时前
WHAT - React 进一步学习推荐
前端·学习·react.js
kovlistudio1 小时前
红宝书第四十讲:React 核心概念:组件化 & 虚拟 DOM 简单教程
开发语言·前端·javascript·学习·react.js·前端框架
zx13232 小时前
chrome提示https不安全, 不能记住账号密码怎么办? 可以利用js输入账号
开发语言·javascript·ecmascript
巴巴_羊2 小时前
React Redux
开发语言·前端·javascript
Mintopia2 小时前
Node.js 中的this
前端·javascript·node.js