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

JavaScript基础之深拷贝浅拷贝

什么是深拷贝,什么是浅拷贝?

浅拷贝

定义:
创建一个新的数组或者对象,并将原数组或者对象的顶层属性逐一复制到新创建的对象或者数组中。
特点:

  • 对于基本数据类型,直接复制其值。
  • 对于引用类型(对象,数组,方法),仅仅复制该引用。

示例:

// 浅拷贝示例
let origin = { a: 1, nested: { b: 2 } };
let copy = Object.assign({}, origin);

copy.nested.b = 3;
console.log(origin.nested.b); //3

copy.a = 4;
console.log(origin.a); //1

在这个示例中,我们修改了拷贝的新对象的nested对象的b属性的值,原始对象的nested对象的b属性值也跟着发生了改变。而修改拷贝对象属性a的值,原始对象的属性a的值没有跟着改变。

实现方法:
1.使用Object.assign方法
这是js给我们提供的浅拷贝方法。

let newObj = Object.assign({}, oldObj);

2.使用扩展运算符

let newObj = {...oldObj};

3.手动实现浅拷贝函数

function shallowCopy(obj) {
  let clone = {};
  for (let key in obj) {
    //这个判断是为了避免拷贝到原型链上的属性
    //继承过来的属性可能存在风险,影响性能和安全
    if (obj.hasOwnProperty(key)) {
      clone[key] = obj[key];
    }
  }
  return clone;
}

const copyObj = shallowCopy({ a: 1, nested: { b: 2 } });
console.log(copyObj);

这里需要说明的是obj.hasOwnProperty(key)这个判断是有必要加的,不加的话,在原型对象被修改的时候,修改的属性也会被继承,虽然也能实现浅拷贝功能,但主要的问题是我们不知道原型属性怎么被修改,存在不可控性,继承过来的属性可能存在风险,影响性能和安全。

深拷贝

定义:
不仅仅复制第一层的属性,并且会递归的复制子对象及其后代的属性,从而生成一个完全独立的新对象。
特点:

  • 修改拷贝对象不会影响原对象,哪怕是修改子对象的任何嵌套属性。拷贝对象和原对象完全独立。

示例:

const originObj = { a: 1, nested: { b: 2 } };
const newDeepObj = JSON.parse(JSON.stringify(originObj));

newDeepObj.nested.b = 3;
console.log(newDeepObj); //{ a: 1, nested: { b: 3 } }
console.log(originObj); //{ a: 1, nested: { b: 2 } }

因为是深拷贝,及时新对象的嵌套引用类型属性被修改了,原对象对应的属性也没有跟着改变,两者互不影响。

注意事项:
这种实现方式存在一定的局限性。要想实现完美的深拷贝,需要手动实现深拷贝函数。

常见实现方式:
1.通过JSON.stringify()和JSON.parse()
如前面所示,存在局限性。
2.通过递归实现深拷贝

function deepCopy(obj) {
  //如果是null或者基本数据类型直接返回。(在js中,typeof对象和数组都返回"object")
  if (obj === null || typeof obj !== "object") {
    return obj;
  }
  //经过第一个判断,现在obj只可能是数组或者对象

  //如果是数组
  if (Array.isArray(obj)) {
    let copy = [];
    for (let i in obj) {
      copy[i] = deepCopy(obj[i]);
    }
    return copy;
  }

  let copy = {};
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      copy[key] = deepCopy(obj[key]);
    }
  }
  return copy;
}

let origin = { a: 1, nested: { b: 2 }, arr: [1, 2, 3] };
let copy = deepCopy(origin);
console.log(copy);

上面代码中的两个for循环代码是一样的,所以可以简化成下面的代码。虽然比较难以理解,但代码量更少。

function deepCopy(obj) {
  //如果是null或者基本数据类型直接返回。(在js中,typeof对象和数组都返回"object")
  if (obj === null || typeof obj !== "object") {
    return obj;
  }
  //经过第一个判断,现在obj只可能是数组或者对象

  let copy = Array.isArray(obj) ? [] : {};

  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      copy[key] = deepCopy(obj[key]);
    }
  }
  return copy;
}

let origin = { a: 1, nested: { b: 2 }, arr: [1, 2, 3] };
let copy = deepCopy(origin);
console.log(copy);

问题:浅拷贝修改内容会影响原对象,这是否存在风险?

是的,是会存在风险。所以浅拷贝的使用是有限制的。当然,就是用在需要修改原对象的场景。使用浅拷贝的好处是效率更高,不需要递归遍历子对象。同时浅拷贝的有下面的优点。
性能优化

  • 速度更快: 浅拷贝只需要复制对象的第一层属性,而不必递归地复制整个对象树,因此执行速度快。
  • 内存消耗低: 由于只需分配少量额外的空间来存储新对象的基本结构,而不是完整的内容,内存占用较低。

简化代码

  • 在简单的数据结构中,浅拷贝可以使代码更加简洁易读。
  • 适合那些不需要深层次分离的对象。

共享不可变数据

  • 在某些设计模式中,允许多个部分共享同一份不变的数据是有益的。浅拷贝在这种情况下非常有用。

总结

浅拷贝深拷贝
复制层次第一层全部层级
引用关系新旧对象共用部分引用彼此独立无关联
应用场景数据不需要隔离的情况下当你需要保证操作某个对象时不干扰其他相关联的对象

http://www.kler.cn/a/555633.html

相关文章:

  • Python 高级特性-切片
  • 网络安全知识:网络安全概念、内容和主要技术纵览
  • Hive JSON解析终极武器:魔改`json_tuple`源码支持嵌套路径完整指南
  • 七星棋牌源码高阶技术指南:6端互通、200+子游戏玩法深度剖析与企业级搭建实战(完全开源)
  • 【Server Components 解析:Next.js 的未来组件模型】
  • 最新本地部署 DeepSeekR1 蒸馏\满血量化版 + WebOpenUI 完整教程(Ubuntu\Linux系统\Ollama)
  • 【WPS+VBA】表格中重复表头与页码的批量删除
  • C/C++ 指针避坑20条
  • KT142C语音芯片支持的语音文件格式什么?Mp3还是wav呢?
  • 【Unity 游戏引擎插件】Modular Multiplayer FPS Engine (Mirror) (MMFPSE) 专注于帮助开发者快速构建多人第一人称射击(FPS)游戏
  • AI助力下的PPT革命:DeepSeek 与Kimi的高效创作实践
  • SQLMesh 系列教程7- 详解 seed 模型
  • 发现一个挺好的项目,可以在springboot项目中快速接入DeepSeek API,有需要的可以尝试一下
  • 技术总结 | MySQL面试知识点
  • 数据库系统概念
  • 自然语言处理NLP 01语言转换语言模型
  • 如何优化 Webpack 的构建速度?
  • 设计模式教程:命令模式(Command Pattern)
  • 使用vue-office报错TypeError: ft.createElementVNode is not a function
  • Casbin 权限管理介绍及在 Go 语言中的使用入门