在jsvaScript中,简单值是通过直复制来进行赋值传递的,而引用类型是通过引用赋值来进行复制传递的。
var a = 2; var b = a; b = 3; console.log(a) //2 console.log(b) //3 var arr1 = [1,2,3]; var arr2 = arr1; arr2.push(4); console.log(arr1); //[1,2,3,4] console.log(arr2); //[1,2,3,4]
第一种情况就是简单值得复制传递,a和b分别在两个内存中,b=a知识吧a的值复制给b,改变b的值不会影响a的值。
第二种情况是引用类型的复制,arr2 = arr1是将arr1的地址复制给arr2,两个数组指向同一片内存区域,所以改变arr2的值也会改变arr1的值。是数组的浅拷贝。
下面来看看什么是数组的深拷贝
var a = [1,2,3]; var b = a.slice(0); var c = a.concat(); b.push(4); c.push(5); console.log(a); //[1,2,3] console.log(b); //[1,2,3,4] console.log(c); //[1,2,3,5]
对象的浅拷贝
function easyClone(Obj) { var objNew = {}; for ( var i in Obj) { objNew[i] = Obj[i]; } return objNew; }
其实就是将每个原对象的属性和值复制到新对象上去,当然我们也可以使用Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象,同时Object.assign() 也是浅拷贝。
浅拷贝因为没有递归循环检查对象的每个值是否是对象,而是直接进行了赋值,所以如果某个值是对象的时候就会出现问题,所以在一般情况下我们需要用深拷贝来进行备份。
对象的深拷贝
最简单的深拷贝
var b = JSON.parse(JSON.stringify(a))
但是这种深拷贝有一定的局限性,第一:无法复制函数,第二:原形链没了,对象就是object,所属的类没了。
其实简单的深拷贝只需要我们递归调用浅拷贝就可以了:
function deepCopy(obj) { var objNew = objNew || {}; for (var i in obj) { if (typeof p[i] === 'object') { objNew[i] = (p[i].constructor === Array) ? [] : {}; deepCopy(obj[i], objNew[i]); } else { objNew[i] = obj[i]; } } return objNew; }