浅拷贝:创建一个新对象,如果拷贝对象式基础数据类型,复制值给新对象。如果式引用数据类型,复制内存中的地址给新对象。
深拷贝:对于引用数据类型,在堆内存中完全开辟一块地址,并将对象复制过来存放。
浅拷贝的方法:
1.es6中的object.assign()
let target = {};
let source = { a: { b: 2 } };
Object.assign(target, source);
console.log(target); // { a: { b: 10 } };
source.a.b = 10;
console.log(source); // { a: { b: 10 } };
console.log(target); // { a: { b: 10 } };
2.数组的slice()方法
let arr = [1, 2, {val: 4}];
let newArr = arr.slice();
newArr[2].val = 1000;
console.log(arr); //[ 1, 2, { val: 1000 } ]
3.数组的contact()方法
let arr = [1, 2, 3];
let newArr = arr.concat();
newArr[1] = 100;
console.log(arr); // [ 1, 2, 3 ]
console.log(newArr); // [ 1, 100, 3 ]
4.扩展运算符…
let obj = {a:1,b:{c:1}}
let obj2 = {...obj}
obj.a = 2
console.log(obj) //{a:2,b:{c:1}} console.log(obj2); //{a:1,b:{c:1}}
obj.b.c = 2
console.log(obj) //{a:2,b:{c:2}} console.log(obj2); //{a:1,b:{c:2}}
/* 数组的拷贝 */
let arr = [1, 2, 3];
let newArr = [...arr]; //跟arr.slice()是一样的效果
5.手工实现
1.区分基础数据类型和引用数据类型
2.对应用数据类性开辟一个新的存储,并且拷贝一层对象属性。
function shallowClone(target) => {
//判断数据类型
if (typeof target === 'object' && target !== null) {
//开辟存储空间,判断是数组还是对象
const cloneTarget = Array.isArray(target) ? []:{};
//循环遍历原对象,取出对象属性赋给新对象,在进行值的拷贝
for (let prop in target) {
if (target.hasOwnProperty[prop]);
cloneTarget[prop] = target[prop];
}
return cloneTarget;
} else {
return target
}
}
深拷贝:
1.JSON.stringify()
let obj1 = {a:1, b:[1,2,3]}
let str = JSON.stringify(obj1);
let obj2 = JSON.parse(str);
console.log(obj2);
注意!
拷贝的对象的值中如果有函数、undefined、symbol 这几种类型,经过 JSON.stringify 序列化之后的字符串中这个键值对会消失;
拷贝 Date 引用类型会变成字符串;
无法拷贝不可枚举的属性;
无法拷贝对象的原型链;
拷贝 RegExp 引用类型会变成空对象;
对象中含有 NaN、Infinity 以及 -Infinity,JSON 序列化的结果会变成 null;
无法拷贝对象的循环应用,即对象成环 (obj[key] = obj)。
手写递归实现:
通过for- in遍历传入参数的属性值,如果只是引用类型则再次递归调用该函数,如果是基础数据类型就直接复制。
let obj = {
a: {
b:1
}
}
function deepClone(obj) {
let cloneObj = {}
for (let key in obj) {
if (typeof key === 'onject') {
cloneObj[key] = deepClone(obj[key])
}else {
cloneObj[key] = obj[key]
}
}
return cloneObj
}
这个深拷贝函数并不能复制不可枚举的属性以及 Symbol 类型;
这种方法只是针对普通的引用类型的值做递归复制,而对于 Array、Date、RegExp、Error、Function 这样的引用类型并不能正确地拷贝;
对象的属性里面成环,即循环引用没有解决。