Lodash源码阅读-cloneTypedArray

Lodash 源码阅读-cloneTypedArray

概述

cloneTypedArray 是 Lodash 库中的一个内部工具函数,主要用于创建 TypedArray(类型化数组)对象的克隆。TypedArray 是处理二进制数据的专用数组类型,如 Int8Array、Uint8Array、Float32Array 等,这个函数在深度克隆操作中确保了对这类特殊数组的正确处理,支持浅拷贝和深拷贝两种模式。

前置学习

依赖函数

  • cloneArrayBuffer:用于克隆 TypedArray 底层的 ArrayBuffer 对象,在深拷贝模式下使用

技术知识

  • TypedArray:JavaScript 中的类型化数组,包括 Int8Array、Uint8Array、Float32Array 等多种类型
  • ArrayBuffer:类型化数组底层的二进制数据缓冲区
  • 构造函数属性 :JavaScript 对象的 constructor 属性,指向创建该对象的构造函数
  • 浅拷贝与深拷贝:对象复制的两种模式及其在处理引用类型时的区别

源码实现

javascript 复制代码
/**
 * Creates a clone of `typedArray`.
 *
 * @private
 * @param {Object} typedArray The typed array to clone.
 * @param {boolean} [isDeep] Specify a deep clone.
 * @returns {Object} Returns the cloned typed array.
 */
function cloneTypedArray(typedArray, isDeep) {
  var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
  return new typedArray.constructor(
    buffer,
    typedArray.byteOffset,
    typedArray.length
  );
}

实现思路

cloneTypedArray 函数的实现思路清晰直接:

  1. 根据 isDeep 参数决定如何处理 TypedArray 的底层 ArrayBuffer:
    • 如果是深拷贝(isDeep 为 true),则使用 cloneArrayBuffer 函数创建底层 ArrayBuffer 的独立副本
    • 如果是浅拷贝(isDeep 为 false 或未提供),则直接使用原始 TypedArray 的 buffer 引用
  2. 使用原始 TypedArray 的构造函数创建一个新的 TypedArray 实例,传入处理后的 buffer、原始的字节偏移量和长度
  3. 返回新创建的 TypedArray 对象

这种实现方式既可以创建共享底层数据的浅拷贝,也可以创建完全独立的深拷贝,满足不同场景的需求。

源码解析

函数签名

javascript 复制代码
function cloneTypedArray(typedArray, isDeep) {

函数接收两个参数:

  • typedArray:要克隆的类型化数组对象(如 Int8Array、Uint8Array 等)
  • isDeep:可选的布尔值,指定是否进行深拷贝

处理 buffer

javascript 复制代码
var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;

这行代码是函数的核心,它根据 isDeep 参数决定如何处理底层的 ArrayBuffer:

  • 如果 isDeep 为 true,调用 cloneArrayBuffer 函数创建 typedArray.buffer 的深拷贝
  • 如果 isDeep 为 false 或未提供,直接使用原始的 typedArray.buffer 引用

在深拷贝模式下,新创建的 TypedArray 将拥有自己独立的底层数据存储,不会与原始数组共享数据。而在浅拷贝模式下,新旧数组共享同一个底层 ArrayBuffer,对一个数组的修改会影响另一个。

创建新的 TypedArray

javascript 复制代码
return new typedArray.constructor(
  buffer,
  typedArray.byteOffset,
  typedArray.length
);

这行代码创建并返回一个新的 TypedArray 对象:

  1. 通过 typedArray.constructor 获取原始类型化数组的构造函数(如 Int8Array、Float32Array 等)
  2. 使用该构造函数创建一个新的类型化数组实例,传入三个参数:
    • buffer:上一步获取或创建的 ArrayBuffer
    • typedArray.byteOffset:原始类型化数组的字节偏移量
    • typedArray.length:原始类型化数组的长度(元素个数)

使用 constructor 属性而不是硬编码特定的构造函数,使得这个函数可以处理所有类型的 TypedArray,保持了代码的通用性和扩展性。

不同类型的 TypedArray

JavaScript 提供了多种类型化数组,cloneTypedArray 可以处理所有这些类型:

  • Int8Array:8 位有符号整数数组
  • Uint8Array:8 位无符号整数数组
  • Uint8ClampedArray:8 位无符号整数数组(固定范围)
  • Int16Array:16 位有符号整数数组
  • Uint16Array:16 位无符号整数数组
  • Int32Array:32 位有符号整数数组
  • Uint32Array:32 位无符号整数数组
  • Float32Array:32 位浮点数数组
  • Float64Array:64 位浮点数数组

无论哪种类型,cloneTypedArray 都能通过 constructor 属性正确地创建对应类型的克隆。

浅拷贝与深拷贝的区别

javascript 复制代码
// 浅拷贝 - 共享同一个底层 ArrayBuffer
var shallowClone = cloneTypedArray(originalArray, false);

// 深拷贝 - 创建底层 ArrayBuffer 的独立副本
var deepClone = cloneTypedArray(originalArray, true);

// 修改测试
shallowClone[0] = 99; // 也会修改 originalArray[0]
deepClone[0] = 99; // 不会影响 originalArray[0]

浅拷贝和深拷贝的关键区别在于对底层 ArrayBuffer 的处理:

  • 浅拷贝创建的新数组与原始数组共享同一个底层 ArrayBuffer,任何一方的修改都会影响另一方
  • 深拷贝通过复制底层 ArrayBuffer 创建完全独立的新数组,两个数组之间的修改互不影响

总结

cloneTypedArray 是 Lodash 中一个专门用于克隆类型化数组的工具函数,它通过灵活处理底层 ArrayBuffer,实现了对各种类型化数组的浅拷贝和深拷贝。

这个函数的实现体现了几个重要的软件设计原则:

  1. 通用性 :使用 constructor 属性使函数能够处理所有类型的 TypedArray
  2. 灵活性 :通过 isDeep 参数支持浅拷贝和深拷贝两种模式
  3. 组合复用 :利用 cloneArrayBuffer 函数处理底层数据的复制,避免代码重复
  4. 单一职责:函数只关注于类型化数组的克隆,遵循"做好一件事"的原则

在处理二进制数据和数值计算的 JavaScript 应用中,cloneTypedArray 提供了一种简洁而强大的方式来创建类型化数组的副本,为数据处理提供了更多的灵活性和安全性。

相关推荐
mayaairi6 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen6 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马7 小时前
AI源码分析:拆解模型底层实现逻辑
前端
BillKu7 小时前
全局样式变量:CSS 自定义属性(--border-color)和SCSS 变量($border-color)的说明
javascript·css·scss
IT_陈寒7 小时前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端
乘风gg8 小时前
DeepSeek V4.1 Flash 来了,明天中午 Flash 降价 60%
前端·ai编程·claude
默_笙8 小时前
❗ 给金鱼装记忆(上):从白板到笔记本,AI 的短期记忆生存指南
前端·javascript
酷酷的逗逗乐8 小时前
前端转 Agent 开发 · 第五节:Memory 会话记忆
前端·程序员
掘金挖土8 小时前
前端手摸手跑路之 AI 应用开发(二)
前端·后端
兜里只有三分钱~8 小时前
翻卡_3D 的仪式感,和三个让它穿帮的写法
javascript·css·3d