首先js 的数据类型有基本类型和引用类型 基本类型: number,string,boolean,null,underfined ---- 数据存放在栈中 引用类型:object,Array —数据存放在堆中,栈存放指真指向堆中的真实数据 浅拷贝和深拷贝都是指object,Array这种引用类型, 浅拷贝:复制的是栈中的指真 不会开辟新的空间 因此指向同一个堆,无论哪个对象改变都会改变堆中的数据,一变都变 深拷贝:复制一个一样的对象并开辟一个新的内存空间,因此这个对象没有关联,不会相互影响
对象的拷贝
//浅拷贝 let a={ x:1, y:2 } let b=a; b.x=2; b.y=1; console.log(a); //x=2 ,y=1 console.log(b); //x=2 ,y=1 //深拷贝 let a={ x:1, y:2 } let b=Object.assign({},a); b.x=2; b.y=1; console.log(a); //x=1 ,y=2 console.log(b); //x=2 ,y=1 //但是当对象两层时 let a={ x:1, y:2, d:{ z:1 } } let b=Object.assign({},a); b.x=2; b.y=1; // 这时x y 是深拷贝 console.log(a); //x=1 ,y=2 ,z=1 console.log(b); //x=2 ,y=1,z=1 //当改变d中的值时d就是浅拷贝了 b.d.z=9; console.log(a); //x=1 ,y=2 ,z=9 console.log(b); //x=2 ,y=1,z=9 //这时再用Object.assign深拷贝就不合适了 //这时就应该使用JSON.parse(JSON.stringify(a))开进行深拷贝 let g=JSON.parse(JSON.stringify(a)) g.x=2; g.y=1; g.d.z=9; console.log(a); //x=1 ,y=2 ,z=1 console.log(g); //x=2 ,y=1 ,z=9数组的拷贝
//如果数组中不包含引用类型 Array.concat() 和 Array.slice()都能实现深拷贝 let a=['1','2']; let b=a.slice(); //let b=a.concat(); b[0]=99; console.log(a); // ['1','2']; console.log(b); // [99,'2']; //当数组中包含引用类型时 该引用类型无法被深拷贝 let a=['1','2',{a:'dd'}]; let b=a.slice(); //let b=a.concat(); b[2].a='cc'; console.log(a); // ['1','2',{a:'cc'}]; console.log(b); // [99,'2',,{a:'cc'}];因此在需要进行深拷贝的时候无论数组还是对象使用JSON.parse(JSON.stringify(a)) 就可以避免这种问题