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
函数的实现思路清晰直接:
- 根据
isDeep
参数决定如何处理 TypedArray 的底层 ArrayBuffer:- 如果是深拷贝(
isDeep
为 true),则使用cloneArrayBuffer
函数创建底层 ArrayBuffer 的独立副本 - 如果是浅拷贝(
isDeep
为 false 或未提供),则直接使用原始 TypedArray 的 buffer 引用
- 如果是深拷贝(
- 使用原始 TypedArray 的构造函数创建一个新的 TypedArray 实例,传入处理后的 buffer、原始的字节偏移量和长度
- 返回新创建的 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 对象:
- 通过
typedArray.constructor
获取原始类型化数组的构造函数(如 Int8Array、Float32Array 等) - 使用该构造函数创建一个新的类型化数组实例,传入三个参数:
buffer
:上一步获取或创建的 ArrayBuffertypedArray.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,实现了对各种类型化数组的浅拷贝和深拷贝。
这个函数的实现体现了几个重要的软件设计原则:
- 通用性 :使用
constructor
属性使函数能够处理所有类型的 TypedArray - 灵活性 :通过
isDeep
参数支持浅拷贝和深拷贝两种模式 - 组合复用 :利用
cloneArrayBuffer
函数处理底层数据的复制,避免代码重复 - 单一职责:函数只关注于类型化数组的克隆,遵循"做好一件事"的原则
在处理二进制数据和数值计算的 JavaScript 应用中,cloneTypedArray
提供了一种简洁而强大的方式来创建类型化数组的副本,为数据处理提供了更多的灵活性和安全性。