唯品秀前端博客

数据深拷贝是实际项目中你总有一天或者必然会遇到的问题,甚至很多人可能对这两个概念并不是很清晰。简单来说,深拷贝就是把一条数据A复制出来个副本B,修改副本B数据并不会影响原来数据A,浅拷贝则反之,修改数据B会影响到原来的A数据。下面总结下又哪些处理深拷贝的方法(下列方法demo均来自于互联网,本文章主要用于总结归档,方便后人查阅

浅拷贝

1
2
3
4
5
let a=[0,1,2,3,4],
    b=a;
console.log(a===b);
a[0]=1;
console.log(a,b);

为什么会出现上面这种情况?

那么这里,就得引入基本数据类型与引用数据类型的概念了。面试常问,基本数据类型有哪些,number,string,boolean,null,undefined,symbol以及未来ES10新增的BigInt(任意精度整数)七类。引用数据类型(Object类)有常规名值对的无序对象{a:1},数组[1,2,3],以及函数等。

实现简单的深拷贝

1、slice和concat

这两个方法特性是将原来的数据产生一个副本,不会去改变原来的数据,但它有一定的局限性,如果数据是基本数据类型,那是可以的,否则,就会有问题。

1
2
3
var a= [0,1,2,3,4];
var b= a.slice(0); // 通过slice方法,参数为0,意味着拷贝数组arr1的0 - 最后一位
b[1] = "9";

2、Object.assign()方法

这个方法和上面的slice和concat方法有同样的弊端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var Jack ={
    code:'0001',
    name:'张三',
    assing:function () {
        alert('张三签到');
    },
    car:{
        name:'路虎',
        type:'SVR'
    }
}
 
var Tom = Object.assign({},Jack);
Tom.name = '赵四';
console.log(Jack);
console.log(Tom);
Tom.car.name='宝马';
console.log(Jack);
console.log(Tom);

3、Json.parse(Json.stringify(obj))方式

我太难了,看了上面几种方法,都不能达到要求,那么Json.parse又会如何呢?该方法成功实现了嵌套属性的深拷贝,但是原对象中的assign()方法丢失了。这是因为JSON.stringify()方法将对象转化为字符串,但只会处理简单属性和简单属性数组,constructor属性丢失了。也就是说他中间变换了形态,从对象—>字符串—>对象,最终把原对象该有的自身方法弄丢了,如果你不介意,自然是可以的,因此,除非对象只有简单属性,没有constructor信息,才能使用Json.parse(Json.stringify(obj))做深拷贝。

1
2
3
4
5
var Alex = JSON.parse(JSON.stringify(Jack));
Alex.name='王五';
Alex.car.name='劳斯莱斯';
console.log(Jack);
console.log(Alex);

4、es6中的 Object.create()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function deepClone(initalObj, finalObj) {    
  var obj = finalObj || {};    
  for (var i in initalObj) {        
    var prop = initalObj[i];  // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况
    if(prop === obj) {            
      continue;
    }        
    if (typeof prop === 'object') {
      obj[i] = (prop.constructor === Array) ? [] : Object.create(prop);
    } else {
      obj[i] = prop;
    }
  }    
  return obj;
}

那么到底如何实现复杂的数据结构深拷贝?

自己封装个简单方法是个不错的选择

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
function deepClone(obj) {
    let objClone = Array.isArray(obj) ? [] : {};
    if (obj && typeof obj === "object") {
        for (key in obj) {
            if (obj.hasOwnProperty(key)) {
                //判断ojb子元素是否为对象,如果是,递归复制
                if (obj[key] && typeof obj[key] === "object") {
                    objClone[key] = deepClone(obj[key]);
                } else {
                    //如果不是,简单复制
                    objClone[key] = obj[key];
                }
            }
        }
    }
    return objClone;
}

var obj1 = {
    a: 1,
    b: [{ x: 1, y: 2 }],
    c: {
        d: [{bb: 100}]
    }
}
var obj2 = deepClone(obj1);
obj2.a = 3;
obj2.b[0].x = 10;
obj2.b[0].y = 20;
obj2.c.d[0].bb = 200;
console.log(obj1,obj2)

借助函数库lodash实现深拷贝

这个方法库特别强大,可以极大的提高工作中处理数据效率。

1
2
3
4
5
var objects = [{ 'a': 1 }, { 'b': 2 }];
 
var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);
// => false

小结

说了这么多,了解深拷贝也不仅仅是为了应付面试题,在实际开发中也是非常有用的。例如后台返回了一堆数据,你需要对这堆数据做操作,但多人开发情况下,你是没办法明确这堆数据是否有其它功能也需要使用,直接修改可能会造成隐性问题,深拷贝能帮你更安全安心的去操作数据,根据实际情况来使用深拷贝,大概就是这个意思。

本站所有文章、图片、资源等如无特殊说明或标注,均为来自互联网或者站长原创,版权归原作者所有;仅作为个人学习、研究以及欣赏!如若本站内容侵犯了原著者的合法权益,可联系我们进行处理,邮箱:343049466@qq.com
赞(4) 打赏
标签:

上一篇:

下一篇:

相关推荐

0 条评论关于"关于js深拷贝与浅拷贝的区别,实现深拷贝的几种方法"

表情

最新评论

    暂无留言哦~~
谢谢你请我吃鸡腿*^_^*

支付宝扫一扫打赏

微信扫一扫打赏