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. 组合式实现

    • 通过组合多个小函数完成功能
    • 每个函数专注做好一件事,代码更清晰易维护
相关推荐
崔庆才丨静觅10 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606111 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了11 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅11 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅11 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅12 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment12 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅12 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊12 小时前
jwt介绍
前端
爱敲代码的小鱼12 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax