JavaScript高级:深浅拷贝

目录

1 引言

2 浅拷贝

2.1 拷贝数组

 1.2 拷贝对象

3 赋值操作和浅拷贝的比较

4 深拷贝

4.1 前置知识 --> 递归函数

4.2 使用递归实现深拷贝

4.3 js库中的lodash里面的cloneDeep内部实现深拷贝

4.4 利用JSON实现深拷贝


深浅拷贝只针对引用数据类型

1 引言

假如我们想要使用一个对象,我们之前通常使用赋值的方式,但是使用赋值的方式时,修改赋值后的对象中的数据,会影响原对象!!!

比如:

const obj = {
      name: '张三',
      age: 18,
}
console.log(obj)
const obj2 = obj;
obj2.name = '李四'
console.log(obj2)
console.log(obj)


而上述的代码只是修改了简单数据类型,如果修改复杂数据类型结果更是如此了!!!

2 浅拷贝

浅拷贝遇到复杂的数据类型拷贝的是地址

2.1 拷贝数组

方式一:

const arr1 = [1, 2, 3]
const arr = [...arr1]
console.log(arr)
arr[0] = 100
console.log(arr)
console.log(arr1)


方式二:

const arr1 = [1, 2, 3]
const arr2 = arr1.concat()
console.log(arr2)
arr2[0] = 100
console.log(arr2)
console.log(arr1)

以上两种方式可以实现单层数组的拷贝,那么如果我们遇到嵌套的数组,使用这种方式还可以吗? 

例:

const arr1 = [1, [1, 2, 3], 3]
const arr2 = arr1.concat()
console.log(arr2)
arr2[1][2] = 100
console.log(arr2)
console.log(arr1)

此时我们修改拷贝后得到的数组中的数据发现,原数组也被修改了。所以当遇到单层的数组时,拷贝时,数组中只是简单数据类型,修改不会影响原数组,但是如果是嵌套的数据,数组中包含数组,那么拷贝是是直接将内层数组作为一个元素拷贝,数组属于复杂数据类型,所以最终拷贝的是地址


 1.2 拷贝对象

比如以下代码:

const obj = {
      name: '张三',
      age: 18,
      height: 1.88,
      family: {                        
          father: '李四',
          mother: '王五'
      }
}

方式一:

const o = { ...obj }
console.log(o)
o.name = '李四'
console.log(o)
console.log(obj)


方式二:

const o = Object.assign({}, obj)
console.log(o)
o.age = 20
o.family.father = '赵六'
console.log(o)
console.log(obj)

在上面的这段代码中,我们修改拷贝后的对象中的复杂数据类型,结果如下:


3 赋值操作和浅拷贝的比较

1、直接赋值的方式,只要是对象都会相互影响,因为都是直接拷贝的是栈中的地址。

2、浅拷贝如果是一层对象不会相互影响,如果出现多层对象,还是会相互影响。(因为如果拷贝的对象中是简单数据类型,直接拷贝的是值,如果是复杂数据类型拷贝的还是地址)

--->   浅拷贝在直接赋值的不足之处进行了改进,而浅拷贝同样也是需要改进,接下来将介绍深拷贝,将解决浅拷贝的不足之处

4 深拷贝

4.1 前置知识 --> 递归函数

首先递归函数是什么?简单理解就是自己调用自己。

1 例:实现阶乘

【代码】:

function fn(n) {
    if (n <= 1)
         return 1
    return n * fn(n - 1)
}
const re = fn(5)
console.log(re)

2 案例:利用递归函数实现setTimeout 模拟setInterval效果

【代码】:

function getTime() {
    document.querySelector('div').innerHTML = new Date().toLocaleString()
    setTimeout(getTime, 1000)
}
getTime()

4.2 使用递归实现深拷贝

const obj = {
    name: '张三',
    age: 18,
    hobby: ['学习', '喝酒', '烫头'],
    family: {
         father: '张三丰',
         mother: '张三娘'
    }
}

【需求】:现在需要拷贝上述 obj 对象中的所有数据,并且修改拷贝后的对象,不管修改的是简单数据类型,还是复杂数据类型,都不会影响原对象

const obj1 = {}

// 拷贝函数
function deepClone(obj1, obj) {  // onj1是新对象,  obj是旧的
    for (let key in obj) {
        // 处理数组的问题
        if (obj[key] instanceof Array) {
              obj1[key] = []
              deepClone(obj1[key], obj[key])
        } else if (obj[key] instanceof Object) {  // 处理对象的问题  因为arr 也属于对象, 所以判断对象时,写在后面
              obj1[key] = {}
              deepClone(obj1[key], obj[key])
         } else {  // 处理其他数据类型的问题

              obj1[key] = obj[key]
         }
     }
}

deepClone(obj1, obj)
obj1.age = 30
obj1.hobby[0] = '睡觉'
console.log(obj1)
console.log(obj)


4.3 js库中的lodash里面的cloneDeep内部实现深拷贝

1. 首先引入lodash.js文件

也可以使用 npm 直接安装

$ npm i -g npm
$ npm i --save lodash

2 【代码】:

const obj = {
     name: '张三',
     age: 18,
     height: 1.88,
     family: {  // 遇到这种复杂数据类型,拷贝的还是地址, 修改会相互影响
          father: '李四',
          mother: '王五'
     }
}

const obj1 = _.cloneDeep(obj)
obj1.family.father = '赵六'
console.log(obj1)
console.log(obj)



虽然使用js自带的库实现深拷贝比递归的方式简单多了,但是还用引入文件也挺麻烦的,接下来再介绍一种更简单的方式。

4.4 利用JSON实现深拷贝

【代码】:

const obj = {
      name: '张三',
      age: 18,
      height: 1.88,
      family: { 
           father: '李四',
           mother: '王五'
            }
        }

const obj1 = JSON.parse(JSON.stringify(obj))  // 先拿到的是字符串,属于简单数据类型,直接存值

console.log(obj1)
obj1.family.father = '赵六'
console.log(obj1)
console.log(obj)

注意:JSON.stringify()只能处理对象和数组,不能处理函数

  • 30
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是小蟹呀^

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值