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

    • 通过组合多个小函数完成功能
    • 每个函数专注做好一件事,代码更清晰易维护
相关推荐
sasaraku.2 小时前
INP指标
前端
magic 2455 小时前
Spring 命名空间注入:p、c 与 .util 的深度解析
java·前端·spring
钢铁男儿6 小时前
Python基本语法(函数partial)
前端·javascript·python
风清云淡_A6 小时前
【angular19】入门基础教程(三):关于angular里面的响应式数据入门使用
前端·angular.js
green_pine_6 小时前
Vue3学习笔记2——路由守卫
前端·vue.js·笔记·学习
空中湖7 小时前
纯前端专业PDF在线浏览器查看器工具
前端·pdf
七灵微7 小时前
ES6入门---第二单元 模块二:关于数组新增
前端·javascript·es6
GUIQU.7 小时前
【Vue】性能优化与调试技巧
前端·vue.js·性能优化
娃哈哈哈哈呀7 小时前
组件通信-mitt
前端·javascript·vue.js
wuhen_n7 小时前
鼠标悬浮特效:常见6种背景类悬浮特效
前端·css·css3·html5