结构化克隆API的前世今生:从深拷贝到原生力量structuredClone()

简介: 结构化克隆API的前世今生:从深拷贝到原生力量structuredClone()

引言:结构化克隆API的前世今生:从深拷贝到原生力量

在JavaScript的世界里,数据复制是一个常见的需求。尤其是对于复杂的数据结构,如嵌套对象和数组,浅拷贝与深拷贝的概念显得尤为重要。随着技术的发展,我们拥有了structuredClone() API这一强大的内置工具,它不仅解决了深拷贝的问题,还提供了高效的处理机制。本文将通过探讨深浅拷贝概念、手写一个完整的深拷贝方法,并详细解读structuredClone() API的工作原理及其实现,带你走进这个功能强大的API的前世今生。

一、深拷贝与浅拷贝

1. 浅拷贝(Shallow Copy)

浅拷贝是指创建一个新的对象或数组,其元素与原始对象或数组的引用相同,但不包含嵌套对象或数组的独立副本。例如:

let obj = { a: 1, b: { c: 2 } };
let shallowCopy = Object.assign({}, obj);

obj.b.c = 3;
console.log(shallowCopy); // 输出:{ a: 1, b: { c: 3 } }

在这个例子中,虽然shallowCopy是新创建的对象,但是它的b属性指向了与obj.b相同的内存地址,因此当修改obj.b.c时,shallowCopy也会受到影响。

2. 深拷贝(Deep Copy)

深拷贝则是创建一个与原始对象完全独立且内容一致的新对象,包括所有嵌套的对象和数组。这要求递归地复制所有层级的数据。

二、手写一个功能齐全的深拷贝函数

下面是一个简单的深拷贝函数实现,它可以处理基本类型、数组、对象以及它们的嵌套结构:

function deepClone(obj) {
  if (obj === null) return null;
  let cloneObj;
  
  if (Array.isArray(obj)) {
    cloneObj = [];
    for (let i = 0; i < obj.length; i++) {
      cloneObj[i] = deepClone(obj[i]);
    }
  } else if (typeof obj === 'object') {
    cloneObj = {};
    for (let key in obj) {
      if (obj.hasOwnProperty(key)) {
        cloneObj[key] = deepClone(obj[key]);
      }
    }
  } else {
    // 处理基本类型
    return obj;
  }
  
  return cloneObj;
}

let obj = { a: 1, b: { c: 2 } };
let deepCopiedObj = deepClone(obj);

obj.b.c = 3;
console.log(deepCopiedObj); // 输出:{ a: 1, b: { c: 2 } }

三、structuredClone API 的详细解读

structuredClone() 出场

在ECMAScript 6规范之后,Web浏览器引入了一个原生的API——structuredClone(),专门用于深度克隆复杂的数据结构,包括那些自定义类实例无法通过手写方法完美复制的情况。

structuredClone() 是JavaScript中的一个原生API,用于创建给定值的深层拷贝(深克隆)。这个方法使用结构化克隆算法(Structured Clone Algorithm),能够处理包括数组、对象以及一些内置类型在内的复杂数据结构,并且能够正确地复制它们的所有嵌套属性和循环引用。

结构化克隆算法概述

结构化克隆算法可以递归地遍历并复制以下类型的值:

  • 基本类型:如数字、字符串、布尔值
  • null
  • undefined
  • Date 对象
  • RegExp 对象
  • ArrayBuffer, DataView, Int8Array, Uint8Array 等 TypedArray 类型
  • Map 和 Set 对象及其内容
  • 函数对象以外的普通对象及其可枚举属性(不包括原型链)
  • Promise 对象
  • Symbol 类型
  • 循环引用的对象结构

使用方式

let originalObject = { a: 1, b: { c: 2 } };
let clonedObject = structuredClone(originalObject);

// 修改克隆后的对象不会影响原始对象
clonedObject.a = 2;
clonedObject.b.c = 3;

console.log(originalObject); // 输出:{ a: 1, b: { c: 2 } }
console.log(clonedObject);   // 输出:{ a: 2, b: { c: 3 } }

功能特点

  • 深度拷贝:与浅拷贝不同,structuredClone() 不仅复制对象的第一层属性,还会递归复制所有嵌套的对象和数组,确保整个数据结构独立于原始对象。
  • 处理循环引用:该算法能识别并正确处理循环引用的情况,即对象之间相互引用的情况。
  • 性能优化:在实现过程中,算法会维护一个内部映射表以避免对同一对象的重复复制,从而提高效率。

应用场景

structuredClone() 在实际开发中有多种用途,例如:

  • 在Web Workers中传递复杂的数据结构。
  • 将数据持久化存储到IndexedDB中。
  • 创建对象的副本以防止直接修改原有数据。

注意事项

尽管功能强大,但structuredClone()仍有一些限制:

  • 它不能复制函数、正则表达式实例的 lastIndex 属性、Symbol描述符以及其他不可序列化的内部属性。
  • 对于自定义类的实例或包含不可序列化属性的对象,该方法可能无法完全克隆其状态。

相关文章
|
6月前
|
XML Java 数据库连接
MyBatis深入探索:原生API与注解方式实现CRUD操作
MyBatis深入探索:原生API与注解方式实现CRUD操作
118 0
|
6月前
|
敏捷开发 JavaScript 前端开发
❤❤❤【Vue.js最新版】sd.js基于jQuery Ajax最新原生完整版for凯哥API版本❤❤❤
❤❤❤【Vue.js最新版】sd.js基于jQuery Ajax最新原生完整版for凯哥API版本❤❤❤
|
2月前
|
负载均衡 API 数据安全/隐私保护
Zookeeper的客户端-原生的API
Zookeeper的客户端-原生的API
|
3月前
|
存储 JavaScript 前端开发
探索React状态管理:Redux的严格与功能、MobX的简洁与直观、Context API的原生与易用——详细对比及应用案例分析
【8月更文挑战第31天】在React开发中,状态管理对于构建大型应用至关重要。本文将探讨三种主流状态管理方案:Redux、MobX和Context API。Redux采用单一存储模型,提供预测性状态更新;MobX利用装饰器语法,使状态修改更直观;Context API则允许跨组件状态共享,无需第三方库。每种方案各具特色,适用于不同场景,选择合适的工具能让React应用更加高效有序。
61 0
|
6月前
|
API
原生api的缺点 typeof , indexOf 等
原生api的缺点 typeof , indexOf 等
44 0
|
6月前
|
前端开发 JavaScript API
【uni-app】【基于jQuery Ajax】[sd.js]最新原生完整版for凯哥API版本
【uni-app】【基于jQuery Ajax】[sd.js]最新原生完整版for凯哥API版本
|
Web App开发 JavaScript 前端开发
SAP UI5 应用开发教程之四十五 - 如何在 SAP UI5 应用里使用 jQuery 和原生的 DOM API
SAP UI5 应用开发教程之四十五 - 如何在 SAP UI5 应用里使用 jQuery 和原生的 DOM API
|
Web App开发 JavaScript 前端开发
在 SAP UI5 应用中使用浏览器原生的 Fetch API 发起网络请求试读版
在 SAP UI5 应用中使用浏览器原生的 Fetch API 发起网络请求试读版
|
存储 小程序 前端开发
原生微信小程序中进行 API 请求
当在原生微信小程序中进行 API 请求时,封装请求可以提高代码的可维护性和可扩展性。在本篇博客中,我们将一步步介绍如何进一步封装请求,并添加请求超时、拦截器和请求取消功能。
200 0