Lodash源码阅读-cloneDataView

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 函数的实现思路直接明了:

  1. 根据 isDeep 参数决定是否对 DataView 的底层 ArrayBuffer 进行深拷贝:
    • 如果是深拷贝(isDeep 为 true),则使用 cloneArrayBuffer 函数复制底层的 ArrayBuffer
    • 如果是浅拷贝(isDeep 为 false),则直接使用原始 DataView 的 buffer 引用
  2. 使用 DataView 的构造函数,结合提供的 buffer(原始或克隆的)和偏移量信息,创建一个新的 DataView 对象
  3. 返回新创建的 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 对象:

  1. 使用 dataView.constructor(即 DataView 构造函数)创建一个新的 DataView 实例
  2. 传递三个参数:
    • buffer:上一步获取或创建的 ArrayBuffer
    • dataView.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 来支持深拷贝,同时也提供了浅拷贝的选项。

这个函数的实现体现了几个重要的编程原则:

  1. 单一职责:函数只负责一件事情 - 克隆 DataView 对象
  2. 开闭原则 :通过参数化 isDeep 实现了功能的扩展,而不需要修改函数内部实现
  3. 组合复用 :利用 cloneArrayBuffer 函数处理底层 ArrayBuffer 的复制,体现了"组合优于继承"的思想
  4. 防御性编程 :使用 constructor 属性而不是直接引用构造函数,增强了代码的兼容性

在处理二进制数据的应用中,cloneDataView 提供了一种灵活而可靠的方式来创建 DataView 的副本,无论是需要共享底层数据还是完全独立的数据副本。

相关推荐
郭老二4 小时前
【前端】vue3:编译步骤
前端
不在逃避q5 小时前
Trae/Vs Code/Cursor命令行无法跑npm命令
前端·arcgis·npm
夏殇之殁5 小时前
包中创建自定义列表项。 . 使用自定义列表项进行数据绑定 . 将天气预报数据保存到本地内存表,通过LiveBindings进行显示。 ...
服务器·前端·javascript
The Chosen One9855 小时前
高进度算法模板速记(待完善)
java·前端·算法
陈随易5 小时前
MoonBit抓包模块pcap,查看电脑的每一次联网通信
前端·后端·程序员
新中地GIS开发老师6 小时前
WebGIS开发学生作品|低空航天管理与航线规划系统
前端·javascript·webgis·三维gis开发
用户059540174467 小时前
大模型对话记忆持久化踩坑实录:用 Playwright 自动化测了 300 次,终于揪出会话丢失的真凶
前端·css
丙氨酸長鏈7 小时前
Web前端入门第 问:JavaScript 一个简单的 IndexedDB 数据库入门示例
前端·javascript·数据库
kyriewen8 小时前
面试官让我手写虚拟列表——AI生成的版本,快速滚动几下就白屏了
前端·javascript·面试
IT_陈寒8 小时前
Vite热更新失效?你可能漏了这个配置
前端·人工智能·后端