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 提供了一种简洁而强大的方式来创建类型化数组的副本,为数据处理提供了更多的灵活性和安全性。

相关推荐
贵沫末18 分钟前
React——基础
前端·react.js·前端框架
aklry30 分钟前
uniapp三步完成一维码的生成
前端·vue.js
Rubin9337 分钟前
判断元素在可视区域?用于滚动加载,数据埋点等
前端
爱学习的茄子37 分钟前
AI驱动的单词学习应用:从图片识别到语音合成的完整实现
前端·深度学习·react.js
用户38022585982438 分钟前
使用three.js实现3D地球
前端·three.js
程序无bug40 分钟前
Spring 面向切面编程AOP 详细讲解
java·前端
zhanshuo40 分钟前
鸿蒙UI开发全解:JS与Java双引擎实战指南
前端·javascript·harmonyos
JohnYan40 分钟前
模板+数据的文档生成技术方案设计和实现
javascript·后端·架构
撰卢1 小时前
如何提高网站加载速度速度
前端·javascript·css·html
10年前端老司机1 小时前
在React项目中如何封装一个可扩展,复用性强的组件
前端·javascript·react.js