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)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!