IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 【面试题解】JavaScript的深浅拷贝,如何手写深拷贝? -> 正文阅读

[JavaScript知识库]【面试题解】JavaScript的深浅拷贝,如何手写深拷贝?

本系列面试题旨在学会相关知识点,从而轻松应对面试题的各种形式,本文讲解了 JavaScript 中拷贝的相关知识,以及如何手写深浅拷贝。

感觉有帮助的小伙伴请点赞👍鼓励一下 ~

什么是拷贝

拷贝其实就是复制,很多场景需要我们复制一份数据出来,然后对复制后的数据进行操作,可能要求不影响原数据,也可能会要求和原数据产生一些联动。所以根据深拷贝和浅拷贝的功能,就可以满足上述两种要求。

值类型的拷贝

值类型其实没有深浅拷贝之分,亦可以说值类型都是深拷贝。因为值类型拷贝后的值,不会跟原数据产生任何联动,修改拷贝后的值,原数据不会产生任何变化。

  let a = 1
  let b = a
  b = 2
  console.log(a) // => 1
  console.log(b) // => 2

浅拷贝

重新在堆中创建内存,拷贝前后的基本类型互不影响,拷贝前后的引用类型还是会共享同一块内存,故而会相互影响。

先写一个例子来看一下:

  // 定义一个浅拷贝函数
  function shallowCopy(obj) {
    const cloneObj = {}
    for (let i in obj) {
      if (obj.hasOwnProperty(i)) {
        cloneObj[i] = obj[i]
      }
    }
    return cloneObj
  }

  // 声明person
  let person = {
    name: "张三",
    hobbies: ["吃饭", "睡觉", "打豆豆"]
  }

  // 对person进行浅拷贝得到person1
  let person1 = shallowCopy(person)

  //修改值类型
  person1.name = '李四'

  //修改引用类型
  person1.hobbies[0] = '美女'

  console.log(person);
  console.log(person1);

可以看到我们修改 person1 的值类型属性 name ,并没有影响到 personname,但是我们修改引用类型 hobbies 的时候,person 也随着 person1 改变了,这就是浅拷贝。

image.png

除了上面这一种,浅拷贝的实现方式还有 Object.assign()展开运算符...array.slice() array.concat()

深拷贝

从堆内存中开辟一块新的区域存放新对象,对原始对象的所有属性进行递归拷贝,对所有的引用类型的属性同样开辟新区域,修改新对象不会影响原对象。

从上面的浅拷贝的例子中可以看出,personhobbies 虽然是个引用类型,但是 hobbies 的每一个元素都是一个字符串,也就是值类型,所以我们只要再次对 hobbies 进行浅拷贝,那么 hobbies 也就会互不影响了。
所以我们可以得出一个结论,只要对一个对象无限递归进行浅拷贝,最终的结果就是一个深拷贝。

递归浅拷贝

代码如下,要考虑到种种特殊情况。

// 定义一个深拷贝函数
  function deepClone(obj) {
    const cloneObj = new obj.constructor()
    if (obj === null) return obj
    if (obj instanceof Date) return new Date(obj)
    if (obj instanceof RegExp) return new RegExp(obj)
    if (typeof obj !== 'object') return obj
    for (let i in obj) {
      if (obj.hasOwnProperty(i)) {
        cloneObj[i] = deepClone(obj[i])
      }
    }
    return cloneObj
  }

  // 声明person
  let person = {
    name: "张三",
    hobbies: ["吃饭", "睡觉", "打豆豆"]
  }

  // 对person进行浅拷贝得到person1
  let person1 = deepClone(person)

  //修改值类型
  person1.name = '李四'

  //修改引用类型
  person1.hobbies[0] = '美女'

  console.log(person);
  console.log(person1);

结果如下,现在只有李四喜欢美女了。说明我们的深拷贝就成功了。

image.png

JSON.parse(JSON.stringify())

除了上面递归浅拷贝的方式来实现深拷贝之外,还可以使用 JSON.parse(JSON.stringify()) 来达到相同的结果。

但是这种方式有它的弊端,我们来看一下

  // 声明person
  let person = {
    name: "张三",
    hobbies: ["吃饭", "睡觉", "打豆豆"],
    date: new Date,
    fuc: () => { },
    reg: /w/
  }

  // 对person进行浅拷贝得到person1
  const person1 = JSON.parse(JSON.stringify(person));


  //修改值类型
  person1.name = '李四'

  //修改引用类型
  person1.hobbies[0] = '美女'

  console.log(person);
  console.log(person1);

来看一下结果,date 属性从一个对象变成了一个字符串,fuc 属性消失了,reg 属性变成了空对象。所以说这种方式弊端是很大的,一不小心就会有意外产生。

  • undefined、任意的函数以及 symbol 值,在序列化过程中会被忽略;
  • Date 日期会被当做字符串处理;
  • NaNInfinity 格式的数值及 null 都会被当做 null
  • 其他类型的对象,包括 Map/Set/WeakMap/WeakSet,仅会序列化可枚举的属性;
  • 对包含循环引用的对象(对象之间相互引用,形成无限循环)执行此方法,会抛出错误;

image.png

我们再使用递归浅拷贝的方式来看一下结果,简直是一模一样。

image.png

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-11-14 21:32:45  更:2021-11-14 21:34:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:58:09-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码