目录
浅拷贝
深拷贝
与浅拷贝概念:
深浅拷贝出现的前提: 应用类型的数据(对象和数组)
深拷贝就是把目标对象里面的数据一个一个都复制下来,创建出一个一模一样的,存放地
址不一样,互不影响。就像真假美猴王。改变其中一个对象中的内容,另一个对象不会受
到任何影响。
浅拷贝就是单纯的复制内存地址,并没有复制对象本身,新旧两个都共享同一个内存。一荣
俱荣一损共损的样子,任何一个对象里改变某一个属性值,那么另一个也会随之发生改变
**区别:**浅拷贝只能复制第一层,想要深度拷贝的话就要用到深拷贝了
接下来我们就以下面这个obj1对象为例子,进行深浅拷贝的演示
const obj1 = {
a: 1,
b: undefined,
arr: [1, 2, 3],
fun: () => {}
}
浅拷贝
1.Object.assign()方法
const obj2 = Object.assign({},obj1)
缺点:这里就会发现使用Object.assign()只能深拷贝一级属性,二级以上的属性(引用类型)就是浅拷贝了
2.扩展运算符
const obj2 = {...obj1}
缺点:这个方法和上面使用Object.assign()方法使用的结果都是一样的。只能深拷贝一级属性,二级以上属性(引用类型)就是浅拷贝了
深拷贝
1.写一个递归(推荐,比较完美的解决方案)
封装一个DeepClone的深拷贝函数
function DeepClone(data) {
const newData = Array.isArray(data) ? [] : {}
for (let key in data) {
if (data[key] && typeof data[key] === 'object') {
newData[key] = DeepClone(data[key])
} else {
newData[key] = data[key]
}
}
return newData
}
//调用他
const obj2 = DeepClone(obj1)
2.用for…in实现遍历和复制
function deepClone(obj) {
let result = typeof obj.splice === "function" ? [] : {};
if (obj && typeof obj === 'object') {
for (let key in obj) {
if (obj[key] && typeof obj[key] === 'object') {
result[key] = deepClone(obj[key]);//如果对象的属性值为object的时候,递归调用deepClone,即在吧某个值对象复制一份到新的对象的对应值中。
} else {
result[key] = obj[key];//如果对象的属性值不为object的时候,直接复制参数对象的每一个键值到新的对象对应的键值对中。
}
}
return result;
}
return obj;
}
let testArray = ["a", "b", "c", "d"];
let testRes = deepClone(testArray);
console.log(testRes);
console.log(typeof testRes[1]);
let testObj = {
name: "weiqiujuan",
sex: "girl",
age: 22,
favorite: "play",
family: {brother: "son", mother: "haha", father: "heihei"}
};
let testRes2 = deepClone(testObj);
testRes2.family.brother = "weibo";
console.log(testRes2);
3.利用数组的Array.prototype.forEach进copy
let deepClone = function (obj) {
//Object.getPrototypeOf() 方法返回指定对象的原型(内部[[Prototype]]属性的值)。
let copy = Object.create(Object.getPrototypeOf(obj));
//**Object.getOwnPropertyNames()**方法返回一个由指定对象的所有自身属性的属性名
//(包括不可枚举属性但不包括 Symbol 值作为名称的属性)组成的数组。
let propNames = Object.getOwnPropertyNames(obj);
propNames.forEach(function (items) {
// 方法返回指定对象上一个自有属性对应的属性描述符。
//(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)
let item = Object.getOwnPropertyDescriptor(obj, items);
Object.defineProperty(copy, items, item);
});
return copy;
};
let testObj = {
name: "weiqiujuan",
sex: "girl",
age: 22,
favorite: "play",
family: {brother: "wei", mother: "haha", father: "heihei"}
}
let testRes2 = deepClone(testObj);
console.log(testRes2);
4.JSON转换方法
const obj1 = {
a: 1,
b: undefined,
arr: [1, 2, 3],
fun: () => {}
}
const obj2 = JSON.parse(JSON.stringify(obj1))
//这个方法可以,只不过function和undefined这种情况下无法复制
缺点:你看到这里就会发现数据类型是 function 和 undefined 情况下无法复制,其他的都可以进行深层次的拷贝
5.loadash函数库
函数库lodash,也有提供_.cloneDeep用来做深拷贝6.
let lodash = require('lodash');
let list = [{ name: 'Tom' }];
let copyList = lodash.cloneDeep(list);
copyList[0].name = 'Jerry'
console.log(list[0].name); // Tom
console.log(copyList[0].name); // Jerry