何为深拷贝,浅拷贝
浅拷贝:
只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存,拷贝了基本类型的数据,而引用类型数据,复制后也会发生引用,我们把这种拷贝叫做浅拷贝
举个栗子
var obj1 = {a:10, b:20, c:30};var obj2 = obj1; obj2.b = 50;console.log(obj1); // {a:10, b:50, c:30}console.log(obj2); // {a:10, b:50, c:30}
改变了obj2的b,obj1内的值也改变了,这就是浅拷贝
深拷贝:
深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象
举个栗子
function deepCopy(p, c) { var c = c || {}; for (var i in p) { if (typeof p[i] === 'object') { c[i] = (p[i].constructor === Array) ? [] : {}; deepCopy(p[i], c[i]); } else { c[i] = p[i]; } } return c; }let obj1 = {a:10 , b:20, c:30};let obj2 ={}; deepCopy(obj1,obj2); obj2.b = 50;console.log(obj1); // {a:10, b:20, c:30}console.log(obj2); // {a:10, b:50, c:30}
深拷贝的方式有哪些
广为流传的深拷贝方式有
JSON方式
jQuery的 extend方式
es6 的Object.assign方式
vue的 vue.util.extend 方式
递归拷贝
在打码的过程中,以及面试的时候,常常会被问到如何进行深拷贝,那么传说中的深拷贝的方式是真的深拷贝吗~
来一探究竟吧
JSON方式
这是最常用的深拷贝方式,但是也有一个小缺点
缺点:只有可以转成JSON格式的对象才可以这样用,像function没办法转成JSON。
来测试一下是否能深拷贝呢
var obj1 = {a:10, b:20, c:30};var obj2 = JSON.parse(JSON.stringify(obj1)); obj2.b = 50;console.log(obj1); // {a:10, b:20, c:30}console.log(obj2); // {a:10, b:50, c:30}
下面来测试一下二级属性,是否可以深拷贝呢
var obj1 = {a:10, b:{test:20}, c:30};var obj2 = JSON.parse(JSON.stringify(obj1)); obj2.b.test = 50;console.log(obj1); // {a:10, b:{test:20}, c:30}console.log(obj2); // {a:10, b:{test:50}, c:30}
由此证明JSON确实可以进行深拷贝
jQuery extend方式
$.extend()方法有三个参数,第一个参数默认为false,则为浅拷贝,如果需要深拷贝则改为true
var obj1 = {a:10, b:20, c:30};var obj2 = $.extend(true, {}, obj1); obj2.b = 50;console.log(obj1); // {a:10, b:20, c:30}console.log(obj2); // {a:10, b:50, c:30}
那么我们再来测试一下二级属性
var obj1 = {a:10, b:{test:20}, c:30};var obj2 = $.extend(true, {}, obj1); obj2.b.test= 50;console.log(obj1); // {a:10, b:{test:20}, c:30}console.log(obj2); // {a:10, b:{test:50}, c:30}
证明了$.extend(true, {}, obj1)确实是深拷贝~
既然上面提到了默认为false的时候,是浅拷贝,那么我们来试试是什么效果呢
var obj1 = {a:10, b:20, c:30};var obj2 = $.extend({}, obj1); obj2.b = 50;console.log(obj1); // {a:10, b:20, c:30}console.log(obj2); // {a:10, b:50, c:30}
这里没有互相影响呀, obj2改动了之后并没有影响obj1,那为什么说他是浅拷贝呢,来看一下二级属性
var obj1 = {a:10, b:{test:20}, c:30};var obj2 = $.extend( {}, obj1); obj2.b.test= 50;console.log(obj1); // {a:10, b:{test:50}, c:30}console.log(obj2); // {a:10, b:{test:50}, c:30}
obj2 的修改影响了obj1,obj1的二级属性随之改变了
es6 Object.assign方法
抄起键盘就来试验一下吧
var obj1 = {a:10, b:20, c:30};var obj2 =Object.assign({}, obj1); obj2.b = 50;console.log(obj1); // {a:10, b:20, c:30}console.log(obj2); // {a:10, b:50, c:30}
并木有互相影响,来看下二级属性
var obj1 = {a:10, b:{test:20}, c:30};var obj2 =Object.assign({}, obj1); obj2.b.test = 50;console.log(obj1); // {a:10, b:{test:50}, c:30}console.log(obj2); // {a:10, b:{test:50}, c:30}
二级属性互相影响了,obj2修改后,obj1被改变了!!!, 这是一个假的深拷贝
所以在打码深拷贝的时候不要再使用这个办法啦.....TAT
Vue.util.extend方法
这也是广为流传的一种vue深拷贝方法,话不多说,来试一下
ps:切记Vue一定要引用呀
var obj1 = {a:10, b:20, c:30};var obj2 =Vue.util.extend({}, obj1); obj2.b = 50;console.log(obj1); // {a:10, b:20, c:30}console.log(obj2); // {a:10, b:50, c:30}
没啥毛病,来试一下二级属性
var obj1 = {a:10, b:{test:20}, c:30};var obj2 = Vue.util.extend({}, obj1); obj2.b.test = 50;console.log(obj1); // {a:10, b:{test:50}, c:30}console.log(obj2); // {a:10, b:{test:50}, c:30}
obj2的修改影响了obj1惹!!! 这依然是一个假的深拷贝,慎重使用
递归方式
先来测试下
function deepCopy(p, c) { var c = c || {}; for (var i in p) { if (typeof p[i] === 'object') { c[i] = (p[i].constructor === Array) ? [] : {}; deepCopy(p[i], c[i]); } else { c[i] = p[i]; } } return c; }let obj1 = {a:10 , b:20, c:30};let obj2 ={}; deepCopy(obj1,obj2); obj2.b = 50;console.log(obj1); // {a:10, b:20, c:30}console.log(obj2); // {a:10, b:50, c:30}let obj3 = {d:10, f:{test:20}, e:30};let obj4 = {}; deepCopy(obj3,obj4); obj4.b.test = 50;console.log(obj3); // {a:10, b:{test:20}, c:30}console.log(obj4); // {a:10, b:{test:50}, c:30}
很明显这是真的可以深拷贝啦~~~
最后总结:
深拷贝与浅拷贝你弄明白了吗~~~
知道深拷贝有哪几种了吗
作者:Rain_panda
链接:https://www.jianshu.com/p/a80721e593fa