当前位置: 首页 > news >正文

js 深度克隆

深度克隆(Deep Clone)是指复制一个对象或数组及其所有嵌套结构的副本,使得克隆后的对象与原对象完全独立。JavaScript 提供了一些方法实现深度克隆,但每种方法有其优缺点。

1. 常用方法

1.1 使用 JSON.parseJSON.stringify

这种方法最简单,但有局限性。

const obj = { a: 1, b: { c: 2 } };
const clone = JSON.parse(JSON.stringify(obj));console.log(clone); // { a: 1, b: { c: 2 } }
console.log(clone === obj); // false
console.log(clone.b === obj.b); // false
优点
  • 简单易用。
  • 适用于纯 JSON 格式的数据。
缺点
  • 不支持函数、undefinedSymbol、循环引用等。
  • 日期对象会变成字符串,RegExp 对象会丢失。

1.2 使用 structuredClone

structuredClone 是一种内置的深拷贝方法,支持复杂数据结构。

const obj = { a: 1, b: { c: 2 }, d: new Date() };
const clone = structuredClone(obj);console.log(clone); // { a: 1, b: { c: 2 }, d: Date }
console.log(clone === obj); // false
console.log(clone.b === obj.b); // false
优点
  • 支持更多类型(如 DateRegExpMapSet 等)。
  • 处理循环引用。
缺点
  • 不支持旧版本浏览器。
1.3 使用递归实现深度克隆

通过递归遍历对象和数组,手动实现深拷贝。

function deepClone(obj) {if (obj === null || typeof obj !== 'object') {return obj;}if (obj instanceof Date) {return new Date(obj);}if (obj instanceof RegExp) {return new RegExp(obj);}const clone = Array.isArray(obj) ? [] : {};for (const key in obj) {if (obj.hasOwnProperty(key)) {clone[key] = deepClone(obj[key]);}}return clone;
}const obj = { a: 1, b: { c: 2 }, d: new Date() };
const clone = deepClone(obj);console.log(clone); // { a: 1, b: { c: 2 }, d: Date }
console.log(clone === obj); // false
console.log(clone.b === obj.b); // false
优点
  • 完全控制克隆逻辑。
  • 支持特定类型的处理。
缺点
  • 不支持循环引用,需额外处理。

2. 循环引用处理

对于有循环引用的对象,需要使用 WeakMap 来避免递归陷入死循环。

function deepClone (value, cache = new WeakMap ()) {if (typeof value !== "object" || value === null) {return value;}if (cache.has(value)) {return cache.get(value);}const result = Array.isArray(value) ? [] : {};Object.setPrototypeOf(result, Object.getPrototypeOf(value));cache.set(value, result);for (i in value) {if (value.hasOwnProperty(i)) {result[i] = deepClone(value[i], cache);}}return result;
}const obj = { a: 1 };
obj.b = obj; // 循环引用let clone = deepClone(obj);
console.log(clone); // { a: 1, b: [Circular] }const Person = function(name, age) {this.name = name;this.age = age;
}Person.prototype.a = 100;clone = new Person('a', 12)console.log(clone);

3. 方法对比

方法支持类型处理循环引用性能易用性
JSON.parse/stringify仅支持 JSON 格式简单
structuredClone支持大部分类型简单
手动递归可定制支持类型否(需扩展)中等
Lodash支持复杂结构和循环引用简单

推荐

  • 数据结构简单:使用 JSON.parseJSON.stringify
  • 现代浏览器:使用 structuredClone
  • 复杂场景:使用 Lodash 或手动实现带循环引用处理的深拷贝函数。

http://www.mrgr.cn/news/81151.html

相关文章:

  • Linux 下SVN新手操作手册
  • Linux文件目录 --- 移动和改名命令MV、强制移动、试探性移动过、按时间移动
  • uniapp 微信小程序 功能入口
  • 麒麟V10,arm64,离线安装docker和docker-compose
  • windows使用zip包安装MySQL
  • 电脑丢失dll文件一键修复的多种方法分析,电脑故障修复攻略
  • (高可用版本)Kubeadm+Containerd+keepalived部署高可用k8s(v1.28.2)集群
  • VIVO Android面试题及参考答案
  • dvwa靶场
  • 《近世代数基础 第二版》思维导图
  • 捋一捋相关性运算,以及DTD和NLP中的应用
  • 汽车IVI中控开发入门及进阶(47):CarPlay开发
  • Linux下Java通过JNI调用C++
  • 004最长回文子串
  • 麒麟V10,arm64,离线安装docker和docker-compose
  • ESP32S3 使用LVGL驱动LCD屏(ST7789主控)
  • jsp-servlet开发
  • 41 stack类与queue类
  • Docker Compose 配置指南
  • CosyVoice安装过程详解
  • 手动修改nginx-rtmp模块,让nginx-rtmp-module支持LLHLS
  • ubuntu22.04安装PaddleX3
  • 项目代码第6讲:UpdownController.cs;理解 工艺/工序 流程、机台信息;前端的“历史 警报/工艺 记录”
  • ShardingSphere(分库分表)
  • 重温设计模式--建造者模式
  • 脚本专题Script