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

JavaScript 里的深拷贝和浅拷贝

JavaScript 里的深拷贝和浅拷贝

JS中数据类型分为基本数据类型引用数据类型

基本类型值指的是那些保存在内存中的简单数据段。包含NumberStringBooleanNullUndefinedSymbol

引用类型值指的是那些保存在内存中的对象,所以引用类型的值保存的是一个指针,这个指针指向对象的地址。引用类型包含Object 类型、Array 类型、Date 类型、RegExp 类型、Function 类型 等。

因为引用类型保存的是指向存储地址的指针,所以我们直接把一个引用类型赋值给另外一个引用类型时候,相当于是把指针赋值过去,实际上两个对象的存储地址是一样的。因此也就导致这两个对象共用地址,只要地址里的数据被修改后,两个对象的值都会改变。

浅拷贝的实现方式

1.Array.concat()
const arr = [1,2,3];
const copy = arr.concat(); 
console.log(copy); // 输出: [1, 2, 3]
2.Object.assign()
const arr= [1,2,3];
const copy1 = Object.assign({}, arr); 
console.log(copy); // 输出: [1, 2, 3]
3.slice()
const arr= [1,2,3];
let copy = arr.slice();  
console.log(copy); // 输出: [1, 2, 3]
4.扩展运算符 …
const arr= [1,2,3];
const copy = [...arr];
console.log(copy); // 输出: [1, 2, 3]

深拷贝

1.JSON.parse()和JSON.stringify()
const obj1 = {x: 1, y: {m: 1}
};
const obj2 = JSON.parse(JSON.stringify(obj1));
console.log(obj2) //{x: 1, y: {m: 1}}

1.这是最简单的方法之一,但它有一些限制,比如不能正确处理函数、undefinedSymbol、循环引用等特殊类型的值。

2.它会抛弃对象的constructor。也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object

3.如果对象中存在循环引用的情况无法正确处理。

2. 递归复制

通过递归函数手动复制对象的每个属性。这种方法可以处理更复杂的对象和特殊情况(如循环引用)。

function deepClone(obj, hash = new WeakMap()) {  if (obj === null) return null; // null 的情况  if (obj instanceof Date) return new Date(obj); // 日期对象直接返回一个新的日期对象  if (obj instanceof RegExp) return new RegExp(obj); // 正则对象直接返回一个新的正则对象  //hash判断该属性是否被复制// 如果循环引用了就用 weakMap 来解决  if (hash.has(obj)) return hash.get(obj);  let allDesc = Object.getOwnPropertyDescriptors(obj);  let cloneObj = Object.create(Object.getPrototypeOf(obj), allDesc);  hash.set(obj, cloneObj);  for (let key of Reflect.ownKeys(obj)) {  if (typeof obj[key] === 'object' && obj[key] !== null) {  cloneObj[key] = deepClone(obj[key], hash);  } else {  cloneObj[key] = obj[key];  }  }  return cloneObj;  
}  // 使用示例  
let original = { a: 1, b: { c: 2 } };  
original.b.d = original; // 创建一个循环引用  
let clone = deepClone(original);  
console.log(clone);  
http://www.lryc.cn/news/410138.html

相关文章:

  • Oracle基础-集合
  • 《浅谈如何培养树立正确的人工智能伦理观念》
  • uniapp实现局域网(内网)中APP自动检测版本,弹窗提醒升级
  • 【Golang 面试 - 进阶题】每日 3 题(六)
  • Unity横板动作游戏 -项目准备
  • 基于Gunicorn + Flask + Docker的高并发部署策略
  • jdk版本管理利器-sdkman
  • Kafka知识总结(事务+数据存储+请求模型+常见场景)
  • C#中重写tospring方法
  • 【机器学习基础】机器学习的数学基础
  • fastapi之零
  • SpringBoot整合PowerJob 实现远程任务
  • 【扒模块】DFF
  • frameworks 之Socket
  • WEB前端开发中如何实现大文件上传?
  • ts给vue中props设置指定类型
  • 模拟实现c++中的list模版
  • 从信息论的角度看微博推荐算法
  • CISC(复杂指令集)与RISC(精简指令集)的区别
  • 自定义数据库连接的艺术:Laravel中配置多数据库连接详解
  • 力扣高频SQL 50题(基础版)第八题
  • 【C++20】从0开始自制协程库
  • Docker 深度解析:从入门到精通
  • [C++] 模板编程-02 类模板
  • 嵌入式C++、STM32、树莓派4B、OpenCV、TensorFlow/Keras深度学习:基于边缘计算的实时异常行为识别
  • C++ //练习 15.30 编写你自己的Basket类,用它计算上一个练习中交易记录的总价格。
  • 3个方法快速找回忘记的PDF文件密码
  • 排序算法:选择排序,golang实现
  • 【测试】博客系统的测试报告
  • PointCLIP: Point Cloud Understanding by CLIP