区分深拷贝与浅拷贝:
假设B复制了A,当修改A时,B随着A发生变化而变化,说明是浅拷贝,反之,如果B不随着A变化而变化,就是深拷贝。
浅拷贝例子:
let A = [2,2,3,4];
let B = A;
console.log(A === B); // true
A[0] = 1;
console.log("A: " + A); // A: [1,2,3,4]
console.log("B: " + B); // B: [1,2,3,4]
基本类型与引用类型
为了更好解释深拷贝与浅拷贝,下面简单地说明一下基本类型与引用类型
JavaScript基本数据类型有五种,Number、String、Boolean、Null、Undefined
JavaScript引用数据类型:Object、Array、Function等
基本类型的键和值都存储在栈内存中。如下图
因为变量a和变量b的处于的栈内存在不同位置,改变变量a的值时,变量b不会随着a改变而改变,这就是深拷贝。
引用类型的键存储在栈内存中,值存储在堆内存中,但是栈内存会提供一个指向堆内存值的地址。
可以看出,A和B的堆地址都指向同一堆内存,当修改A的值时,B会受到影响,随着A的值改变而改变,这就是浅拷贝
实现深拷贝的三种方法
-
利用递归循环复制层级属性
-
function deepClone(obj) { let objClone = Array.isArray(obj) ? [] : {}; if (obj && typeof obj === 'object') { for(key in obj){ if(obj.hasOwnProperty(key)){ // 判断obj子元素是否为对象,如果是,递归复制 if(obj[key] && typeof obj[key] === 'object'){ objClone[key] = deepClone[obj[key]]; }else{ objClone[key] = obj[key]; } } } } return objClone; } let a = [2,2,3,4]; let b = deepClone(a); a[0] = 1; console.log(b) -
JSON对象的parse和stringify
-
function deepClone1(obj){ let _obj = JSON.stringify(obj); let objClone = JSON.parse(_obj); return objClone; } let a = [1,[1,2],3]; let b = deepClone1(a); a[0] = 2; a[1][0] = 2; console.log(b); -
JQ的extend方法
-
/** * JQ的extend方法 * $.extend([deep],target,object1[,(objectN)]) * deep为true则深拷贝,false就浅拷贝 * target为目标对象 * object为源对象 */ let a = [1,[1,2],3]; let b = $.extend(true,[],a); a[0] = 2; a[1][0] = 2; console.log(b);