数据深拷贝是实际项目中你总有一天或者必然会遇到的问题,甚至很多人可能对这两个概念并不是很清晰。简单来说,深拷贝就是把一条数据A复制出来个副本B,修改副本B数据并不会影响原来数据A,浅拷贝则反之,修改数据B会影响到原来的A数据。下面总结下又哪些处理深拷贝的方法(下列方法demo均来自于互联网,本文章主要用于总结归档,方便后人查阅)
那么这里,就得引入基本数据类型与引用数据类型的概念了。面试常问,基本数据类型有哪些,number,string,boolean,null,undefined,symbol以及未来ES10新增的BigInt(任意精度整数)七类。引用数据类型(Object类)有常规名值对的无序对象{a:1},数组[1,2,3],以及函数等。
这两个方法特性是将原来的数据产生一个副本,不会去改变原来的数据,但它有一定的局限性,如果数据是基本数据类型,那是可以的,否则,就会有问题。
1 2 3 | var a= [0,1,2,3,4]; var b= a.slice(0); // 通过slice方法,参数为0,意味着拷贝数组arr1的0 - 最后一位 b[1] = "9"; |
这个方法和上面的slice和concat方法有同样的弊端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
我太难了,看了上面几种方法,都不能达到要求,那么Json.parse又会如何呢?该方法成功实现了嵌套属性的深拷贝,但是原对象中的assign()方法丢失了。这是因为JSON.stringify()方法将对象转化为字符串,但只会处理简单属性和简单属性数组,constructor属性丢失了。也就是说他中间变换了形态,从对象—>字符串—>对象,最终把原对象该有的自身方法弄丢了,如果你不介意,自然是可以的,因此,除非对象只有简单属性,没有constructor信息,才能使用Json.parse(Json.stringify(obj))做深拷贝。
1 2 3 4 5 |
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) |
这个方法库特别强大,可以极大的提高工作中处理数据效率。
1 2 3 4 5 | var objects = [{ 'a': 1 }, { 'b': 2 }]; var deep = _.cloneDeep(objects); console.log(deep[0] === objects[0]); // => false |
说了这么多,了解深拷贝也不仅仅是为了应付面试题,在实际开发中也是非常有用的。例如后台返回了一堆数据,你需要对这堆数据做操作,但多人开发情况下,你是没办法明确这堆数据是否有其它功能也需要使用,直接修改可能会造成隐性问题,深拷贝能帮你更安全安心的去操作数据,根据实际情况来使用深拷贝,大概就是这个意思。
下一篇:Vue3.0源码学习尝鲜-“别再更新了,实在是学不动了”
支付宝扫一扫打赏
微信扫一扫打赏
共 0 条评论关于"关于js深拷贝与浅拷贝的区别,实现深拷贝的几种方法"
最新评论