什么是深拷贝和浅拷贝以及利用递归实现深拷贝

因为有面试的小伙伴问到什么是深拷贝和浅拷贝,以及怎么用代码实现?

我们先来说一下浅拷贝:

var obj = {a:1};
var b = obj;
console.log(b)
// 输出结果为1

这就是浅拷贝

但是浅拷贝会存在一个问题,我们可以通过代码来看一下

var obj = {
  a:1
};
var b = obj;
console.log(b)

我们上面通过浅拷贝拷贝了一个引用类型,如果我们去修改obj会怎么样?

var obj = {
  a:1
};
var b = obj;
// 修改obj里面的a属性
obj.a = 2
console.log(b)
// 输出结果 {a:2}

我们会发现通过浅拷贝一个引用类型,如果修改obj,最终b也会跟着修改,是因为在拷贝的时候,我们只是将引用地址拷贝给了b,也就是说b和obj引用的是同一个对象

所以我们代码就要改良一下,需要将obj里面的元素取出来然后交给b

var obj = {
  a:1
};
var b = {}
for(key in obj){
  b[key] = obj[key]
}
// 修改 obj的属性
obj.a = 2
console.log(b)
// 输出结果 {a:1}

这样就完美的解决了问题哈哈哈

但是我们作为一个好的程序员,要去发现问题,再来看下一个问题,如果obj里面又包含了一个c对象,然后修改c会怎么样

var obj = {
  a:1,
  c:{
    c1:1
  }
};
var b = {}
for(key in obj){
  b[key] = obj[key]
}
// 修改 obj的属性
obj.c.c1 = 2
console.log(b)
// 输出结果为 {a:1,c:{c1:2}}

当我们修改了obj里面的c对象的时候,b里面的c也跟着变化了,原因就是,b里面拷贝的c也是一个引用类型,从而拷贝的只是一个地址,并且还有一个问题,就是我们不知道obj里面有多少层,可能c1里面又包含一个引用类型,并且我们不知道引用类型是对象还是数组,那么我们就要解决这个问题,这样的问题就是深拷贝。

我们可以先利用一个简单方式来实现深拷贝

var obj = {
  a:1,
  c:{
    c1:1,
    c2:2
  }
};
var str = JSON.stringify(obj)
var b = JSON.parse(str)
// 修改 obj的属性
obj.c.c1 = 2
console.log(b)

我们先将需要拷贝的代码利用JSON.stringify转成字符转,然后再利用

JSON.parse将字符转转回对象,即完成拷贝

但是有的面试官会问你,能够利用递归实现吗?回答当然可以

我们就再利用递归来实现深拷贝

递归实现的思路是什么样的?我们来分析一下

  1. 我们肯定要定义一个方法,那么这个方法最终应该返回一个深拷贝的数据

  2. 既然要返回一个数据,我们首先就要定义一个数据,但是数据是对象还是数组?所以需要判断,如果要拷贝的数据是数组,即定义一个数组,如果是一个对象,即定义一个对象

  3. 方法里面怎么拷贝啊?还是一样的利用for in 循环,在循环内部,需要判断,如果是类型是简单类型,直接拷贝,如果是引用类型,就需要在一次的将引用类型里面的值取出来

根据上面的逻辑我们处理一下代码

var obj = {
  a:1,
  c:{
    c1:1,
    c2:2
  }
};
function deepCopy(obj){
 // 判断拷贝的数据是对象还是数组 生成定义的数据
  var copy = Array.isArray(obj)? []:{}
  for(key in obj){
    // 循环的时候如果此项为引用类型,需要 在一次的将引用类型里面的值取出来
    if(typeof obj[key] == 'object'){
     // 再次调用该方法取数据
      copy[key] = deepCopy(obj[key])
    }else{
      copy[key] = obj[key]
    }
  }
  return copy
}
var b = deepCopy(obj)
console.log(b)

至此,一个深拷贝就实现了,
欢迎转发!!!

猜你喜欢

转载自blog.csdn.net/weixin_41819098/article/details/88777797