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 的副本,无论是需要共享底层数据还是完全独立的数据副本。

相关推荐
重生之后端学习25 分钟前
02-前端Web开发(JS+Vue+Ajax)
java·开发语言·前端·javascript·vue.js
布鲁斯的快乐小屋28 分钟前
axios的基本使用
javascript·ajax
繁依Fanyi1 小时前
用 CodeBuddy 实现「IdeaSpark 每日灵感卡」:一场 UI 与灵感的极简之旅
开发语言·前端·游戏·ui·编辑器·codebuddy首席试玩官
来自星星的坤3 小时前
【Vue 3 + Vue Router 4】如何正确重置路由实例(resetRouter)——避免“VueRouter is not defined”错误
前端·javascript·vue.js
香蕉可乐荷包蛋7 小时前
浅入ES5、ES6(ES2015)、ES2023(ES14)版本对比,及使用建议---ES6就够用(个人觉得)
前端·javascript·es6
未来之窗软件服务8 小时前
资源管理器必要性———仙盟创梦IDE
前端·javascript·ide·仙盟创梦ide
liuyang___9 小时前
第一次经历项目上线
前端·typescript
西哥写代码9 小时前
基于cornerstone3D的dicom影像浏览器 第十八章 自定义序列自动播放条
前端·javascript·vue
清风细雨_林木木10 小时前
Vue 中生成源码映射文件,配置 map
前端·javascript·vue.js
FungLeo10 小时前
node 后端和浏览器前端,有关 RSA 非对称加密的完整实践, 前后端匹配的代码演示
前端·非对称加密·rsa 加密·node 后端