Lodash 源码阅读-cloneDataView
概述
cloneDataView
是 Lodash 库中的一个内部工具函数,主要用于创建 DataView 对象的克隆。DataView 提供了对二进制数据缓冲区的低级读写接口,这个函数确保了在克隆复杂对象时能够正确处理 DataView 类型,支持浅拷贝和深拷贝两种模式。
前置学习
依赖函数
- cloneArrayBuffer:用于克隆 DataView 底层的 ArrayBuffer 对象,实现深拷贝时使用
技术知识
- DataView:JavaScript 中用于读写二进制数据缓冲区的底层接口
- ArrayBuffer:表示通用的、固定长度的原始二进制数据缓冲区
- 构造函数属性 :JavaScript 对象的
constructor
属性,指向创建该对象的构造函数 - 浅拷贝与深拷贝:对象复制的两种模式及其区别
源码实现
javascript
/**
* Creates a clone of `dataView`.
*
* @private
* @param {Object} dataView The data view to clone.
* @param {boolean} [isDeep] Specify a deep clone.
* @returns {Object} Returns the cloned data view.
*/
function cloneDataView(dataView, isDeep) {
var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
return new dataView.constructor(
buffer,
dataView.byteOffset,
dataView.byteLength
);
}
实现思路
cloneDataView
函数的实现思路直接明了:
- 根据
isDeep
参数决定是否对 DataView 的底层 ArrayBuffer 进行深拷贝:- 如果是深拷贝(
isDeep
为 true),则使用cloneArrayBuffer
函数复制底层的 ArrayBuffer - 如果是浅拷贝(
isDeep
为 false),则直接使用原始 DataView 的 buffer 引用
- 如果是深拷贝(
- 使用 DataView 的构造函数,结合提供的 buffer(原始或克隆的)和偏移量信息,创建一个新的 DataView 对象
- 返回新创建的 DataView 对象
这种实现方式灵活地支持了浅拷贝和深拷贝两种需求,使得函数可以在不同的克隆场景中使用。
源码解析
函数签名
javascript
function cloneDataView(dataView, isDeep) {
函数接收两个参数:
dataView
:要克隆的 DataView 对象isDeep
:可选的布尔值,指定是否进行深拷贝
处理 buffer
javascript
var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
这行代码根据 isDeep
参数决定如何处理 DataView 的底层 ArrayBuffer:
- 如果
isDeep
为 true,调用cloneArrayBuffer
函数创建dataView.buffer
的深拷贝 - 如果
isDeep
为 false 或未提供,直接使用原始dataView.buffer
的引用
深拷贝确保了新创建的 DataView 有自己独立的底层 ArrayBuffer,任何对新 DataView 的修改都不会影响原始对象。而浅拷贝则保持了对同一底层 ArrayBuffer 的引用,修改会相互影响。
创建新的 DataView
javascript
return new dataView.constructor(
buffer,
dataView.byteOffset,
dataView.byteLength
);
这行代码创建并返回一个新的 DataView 对象:
- 使用
dataView.constructor
(即 DataView 构造函数)创建一个新的 DataView 实例 - 传递三个参数:
buffer
:上一步获取或创建的 ArrayBufferdataView.byteOffset
:原始 DataView 的字节偏移量dataView.byteLength
:原始 DataView 的字节长度
使用 constructor
属性而不是直接使用 DataView
构造函数,是一种防御性编程方法,确保代码在各种环境中的兼容性。
浅拷贝与深拷贝的区别
在 cloneDataView
函数中,浅拷贝和深拷贝的区别在于对底层 ArrayBuffer 的处理:
javascript
// 浅拷贝 - 共享同一个底层 ArrayBuffer
var shallowClone = cloneDataView(originalDataView, false);
// 深拷贝 - 创建底层 ArrayBuffer 的独立副本
var deepClone = cloneDataView(originalDataView, true);
- 浅拷贝:新旧 DataView 指向同一个 ArrayBuffer,一个 DataView 的修改会影响另一个
- 深拷贝:新的 DataView 指向一个独立的 ArrayBuffer 副本,相互之间的修改不会影响对方
总结
cloneDataView
是 Lodash 中一个专门用于克隆 DataView 对象的工具函数,它巧妙地利用了 cloneArrayBuffer
来支持深拷贝,同时也提供了浅拷贝的选项。
这个函数的实现体现了几个重要的编程原则:
- 单一职责:函数只负责一件事情 - 克隆 DataView 对象
- 开闭原则 :通过参数化
isDeep
实现了功能的扩展,而不需要修改函数内部实现 - 组合复用 :利用
cloneArrayBuffer
函数处理底层 ArrayBuffer 的复制,体现了"组合优于继承"的思想 - 防御性编程 :使用
constructor
属性而不是直接引用构造函数,增强了代码的兼容性
在处理二进制数据的应用中,cloneDataView
提供了一种灵活而可靠的方式来创建 DataView 的副本,无论是需要共享底层数据还是完全独立的数据副本。