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

相关推荐
mldong31 分钟前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排1 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60612 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角3 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!3 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰3 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi5 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen5 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马6 小时前
AI源码分析:拆解模型底层实现逻辑
前端
BillKu6 小时前
全局样式变量:CSS 自定义属性(--border-color)和SCSS 变量($border-color)的说明
javascript·css·scss