JS浅拷贝和深拷贝详解

命运对每个人都是一样的,不一样的是各自的努力和付出不同,付出的越多,努力的越多,得到的回报也越多,在你累的时候请看一下身边比你成功却还比你更努力的人,这样,你就会更有动力。

导读:本篇文章讲解 JS浅拷贝和深拷贝详解,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

1、为什么要用到拷贝?

在开发中我们经常需要复制一个对象。如果直接用赋值会有下面问题:

举个例子:

	// 创建一个对象
    const obj = {
      name: '张三',
      age: 18
    }
    // 直接赋值
    const obj1 = obj
    // 对obj1进行修改,obj也会被修改
    obj1.name = '李四'
    console.log(obj1);
    console.log(obj);

在这里插入图片描述

所以为了解决这个问题,我们就需要要用到拷贝

2、浅拷贝

首先浅拷贝和深拷贝只针对引用类型 ,
浅拷贝:拷贝的是地址

2.1 常见方法:

2.1.1 拷贝对象:

两种常见方法:

 Object.assgin() 或者 展开运算符 {...obj} 拷贝对象

Object.assgin( )实现浅拷贝对象

object.assign 将所有可枚举的属性,从一个或多个源对象复制到目标对象。

	const obj = {
      name: '张三',
      age: 18
    }
    const obj1 = {}
    //第一个参数写新对象,第二个参数写旧对象
    Object.assign(obj1,obj)
    console.log(obj1);
    obj1.name = '王五'
    console.log(obj1);
    console.log(obj);

在这里插入图片描述

{...obj}实现浅拷贝对象

扩展运算符可以实现对象的浅复制

 	const obj = {
      name: '张三',
      age: 18
    }
    const obj1 = {...obj} //展开运算符
    console.log(obj1);
    obj1.name = '云山'
    console.log(obj1);
    console.log(obj);

在这里插入图片描述

2.1.2 拷贝数组:

三种常见方法:

Array.prototype.concat()[...arr]
Array.prototype.slice()

Array.prototype.concat()实现浅拷贝数组

concat 方法用来合并数组,也可以用来实现浅拷贝。

	const arr = ['张三','李四','王五','赵六']
    const arr1 = []
    const arr2 = arr1.concat(arr)
    console.log(arr2);
    arr2[0] = '哈哈'
    console.log(arr2);
    console.log(arr);

在这里插入图片描述

[...arr]实现浅拷贝数组

	const arr = ['张三','李四','王五','赵六']
    const arr1 = [...arr]
    console.log(arr1);
    arr1[0] = '雪峰'
    console.log(arr1);
    console.log(arr);

在这里插入图片描述

Array.prototype.slice 实现浅拷贝数组

slice 方法用来复制数组,接受两个参数 startIndex 和 endIndex,
分别为复制开始的索引(包含当前索引的值)和复制结束的索引(不包含当前索引的值,包含结束索引前的值)。
如果不传 endIndex 参数,则从开始索引复制到数组末尾。

	const arr = ['张三','李四','王五','赵六']
    const arr1 = arr.slice()
    console.log(arr1);
    arr1[0] = '穆青'
    console.log(arr1);
    console.log(arr);

在这里插入图片描述
以上是一些浅拷贝的方法,浅拷贝拷贝的只有一层,多层会受影响。

举个例子理解理解一下什么是多层:

	const obj = {
      name: '张三',
      age: 18,
      family:{
        mother:"妈妈"
      }
    }
    const obj1 = {...obj}
    obj1.family.mother = '云云'
    console.log(obj1);
    console.log(obj);

在这里插入图片描述
在给obj1的mother更改为云云后,原对象obj里面的mother也发生了变化,显然这样是不合理的。所以我们就需要用到深拷贝。

3、 深拷贝

首先浅拷贝和深拷贝只针对引用类型
深拷贝:拷贝的是对象,不是地址

3.1常见方法:

3.1.1 通过递归实现深拷贝

我们先来了解一下什么是递归

函数递归: 如果一个函数在内部可以调用其本身,那么这个函数就是递归函数

1、简单理解: 函数内部自己调用自己, 这个函数就是递归函数

2、 递归函数的作用和循环效果类似

3、 由于递归很容易发生“栈溢出”错误(stack overflow),所以必须要加退出条件 return

举个例子理解一下:

 	let n = 1
    // fn就是递归函数
    function fn() {
      console.log('我要打印六次递归函数');
      if (n >= 6) {
        return
      }
      n++
      fn()//函数内部调用自己
    }
    fn()

在这里插入图片描述
了解完什么是递归之后我们就来写一个简版的深拷贝

  const obj = {
      name: '张三',
      age: 18,
      hobby:['健身','游泳'],
      family: {
        mother: '妈妈'
      }
    }
    const obj1 = {}
    function fn(newObj, oldObj) {
      for (let k in oldObj) {
        if (oldObj[k] instanceof Array) {// 判断是否为数组
          newObj[k] = []
          fn(newObj[k], oldObj[k])
        } else if (oldObj[k] instanceof Object) {// 判断是否为对象
          newObj[k] = {}
          fn(newObj[k], oldObj[k])
        } else {
          newObj[k] = oldObj[k]
        }
      }
    }
    fn(obj1, obj)
    console.log(obj);
    obj1.family.mother = '我'
    obj1.hobby[0] = '跑步'
    console.log(obj1);
    console.log(obj);

在这里插入图片描述

我们将新数组obj1的值进行了修改,通过递归的方式后,原对象是没有发生改变的。

注:进行判断的时候,一定要把数组写在对象前面,因为数组也是属于对象,不然判断是否为数组是执行不到的。

3.1.2 通过 lodash/cloneDeep(js库)实现

我们先从官网https://www.lodashjs.com/下载源文件到本地,然后引入到我们HTML文件里面。

我们来看看具体实现:

  <script src="./lodash.min.js"></script>
	const obj = {
      name : '张三',
      age : 18,
      hobby : ['健身','游泳'],
      family:{
        mother:'妈妈'
      }
    }
    const obj1 = _.cloneDeep(obj)
    console.log(obj);
    obj1.family.mother = '云韵'
    console.log(obj1);
    console.log(obj);

在这里插入图片描述

3.1.3 通过JSON.stringify()实现

实现思路:

先通过JSON.stringify()将obj对象转化为字符串,然后通过JSON.parse( ) 将字符串转化为对象,这样两个对象就互不干涉了。

示例:

 const obj = {
      name : '张三',
      age : 18,
      hobby : ['健身','游泳'],
      family:{
        mother:'妈妈'
      }
    }
   const obj2 = JSON.parse(JSON.stringify(obj))
   console.log(obj);
   obj2.family.mother = '美杜莎'
   console.log(obj2);
   console.log(obj);

在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/144069.html

(0)

相关推荐

  • 前端全局控制console.log的输出

    导读:本篇文章讲解 前端全局控制console.log的输出,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

    前端开发 2022年12月30日
    00
  • Vite 3.0 正式发布,下一代前端工具链!

    大家好,我是 CUGGZ。 7 月 13 日,Vite 3.0 正式发布,它被称为下一代的前端工具链。Vite 团队决定至少每年发布一个新的 Vite 主要版本,以与 Node.j…

    2022年11月4日
    00
  • 9 个功能强大的 Vue 输入表单库

    喜欢就关注我们吧 设计不当的表单会使访问者远离你的网站。幸运的是,对Vue开发人员来说,有许许多多的Vue输入表单库可以让表单的制作变得轻而易举。 直观且对用户友好的表单,其好处包…

    2022年10月11日
    00
  • [Vue2]AntDesignVue基于Select封装「多选 + 二级级联+ 可自定义添加item 组件」

    需求场景 在一个下拉选择框中,一个branch对应多个编译命令option, option1和option2是每个branch都固定拥有的选项,同时支持多选,例如最后选择的结果如下…

    2022年11月23日
    00
  • vue3 组件传值(父传子)

    有时候,不是因为你没有能力,也不是因为你缺少勇气,只是因为你付出的努力还太少,所以,成功便不会走向你。而你所需要做的,就是坚定你的梦想,你的目标,你的未来,然后以不达目的誓不罢休的那股劲,去付出你的努力,成功就会慢慢向你靠近。

    导读:本篇文章讲解 vue3 组件传值(父传子),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

    前端开发 2023年5月26日
    00
  • Vue3中 响应式 API ( readonly、shallowReadonly、toRaw、markRaw ) 详解

    勤奋不是嘴上说说而已,而是实际的行动,在勤奋的苦度中持之以恒,永不退却。业精于勤,荒于嬉;行成于思,毁于随。在人生的仕途上,我们毫不迟疑地选择勤奋,她是几乎于世界上一切成就的催产婆。只要我们拥着勤奋去思考,拥着勤奋的手去耕耘,用抱勤奋的心去对待工作,浪迹红尘而坚韧不拔,那么,我们的生命就会绽放火花,让人生的时光更加的闪亮而精彩。

    导读:本篇文章讲解 Vue3中 响应式 API ( readonly、shallowReadonly、toRaw、markRaw ) 详解,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

    前端开发 2023年4月28日
    00
  • 前端从零开始(53)gradients 渐变

    Gradients 渐变 在以前遇到渐变的背景,我们只能选择使用图片,而现在通过 gradients 这个属性就可以实现颜色的渐变。它的实现是通过浏览器生成的,可以当成是矢量图形。…

    2022年6月1日
    00
  • 利用LRU策略实现Axios请求缓存

    导读:本篇文章讲解 利用LRU策略实现Axios请求缓存,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

    前端开发 2022年5月23日
    00
  • 把数组中每个元素用特定的符号拼接到一起产生一个字符串并输出

    导读:本篇文章讲解 把数组中每个元素用特定的符号拼接到一起产生一个字符串并输出,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

    前端开发 2022年12月30日
    00
  • JavaScript学习基础篇(一)

    导读:本篇文章讲解 JavaScript学习基础篇(一),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

    前端开发 2022年11月1日
    00

发表回复

登录后才能评论