JavaScript 里的深拷贝和浅拷贝

JavaScript 里的深拷贝和浅拷贝

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

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

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

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

浅拷贝的实现方式

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

深拷贝

1.JSON.parse()和JSON.stringify()
js 复制代码
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. 递归复制

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

js 复制代码
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);  
相关推荐
名字还没想好☜3 分钟前
Python 的 __call__ 实战:让实例像函数一样被调用,做带状态计数器、缓存器与可配置策略
开发语言·后端·python·缓存·编程语言
skywalk81636 分钟前
第 23 轮方向确定:保护表通用化替代轮。先深入探查剩余保护表依赖场景和任务 6 的四阶段路径,再写任务书。9.14
开发语言·人工智能·光明
杨利杰YJlio11 分钟前
ITSK PE 26U5 测试版解读:组件完善、VMD 修复与服务器支持边界
前端·javascript·后端
夏幻灵12 分钟前
Vue / React 列表渲染中的 key:为什么没有 key,Checkbox 可能“对号跑错”?
前端·javascript·vue.js
無限進步D12 分钟前
VSCode 简介+安装+JavaWeb前端常用插件+简单配置
java·开发语言·css·vscode·html·css3·插件
YWL12 分钟前
vue-time-axis-plus进阶:双进度条+跨空白续播+播放指针,打造专业级监控回放体验
前端·javascript·vue·时间轴
张小姐的猫16 分钟前
【AI大模型接入SDK】 —— SQLite上手
linux·开发语言·c++·人工智能·python·log4j
溪语流沙32 分钟前
【Python项目实战】部署上线:把博客发布到云服务器
服务器·开发语言·python
岁岁种桃花儿40 分钟前
Vue组件第六篇:Vue单文件组件
开发语言·前端·javascript·vue.js
yivifu42 分钟前
创建支持交叉链接且鼠标悬停显示注释框的HTML文件
前端·javascript·html