简单数据类型在栈中 变量指向栈中的值
复杂数据类型在堆中 变量指向栈中的值,这个值是复杂数据在堆中的地址
浅拷贝是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。
深拷贝是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象。
// 最基本的浅拷贝
const person = { name: "张三", sex: "男", friend: { name: "李四", sex: "女" } };
const personShallow = { ...person };
If you want to use a perfect deep copy, use lodash's .cloneDeep 实现完美的深克隆使用 lodash 的.cloneDeep
原理:先把对象转换成字符串,再把字符串转换成对象赋值
缺点:由于 JSON 的属性值不能是 undefined,不能是函数
拷贝的对象的属性值是函数、undefined,属性名是 Symbol()时,会被舍弃
const personDeep = JSON.parse(JSON.stringify(person));
原理:用 for in 遍历对象的每一个属性,如果属性值是对象,使用递归
缺点:数据层级多会栈溢出,无法保持引用
function isObject(obj) {
return typeof obj === "object" && obj !== "null";
}
function deepClone(obj) {
const cloneObj = Array.isArray(obj) ? [] : {};
if (!isObject(obj)) return obj;
for (const key in obj) {
// 只拷贝自身属性,原型上的不拷贝
if (Object.prototype.hasOwnProperty.call(obj, key)) {
// 如果属性值是对象就递归,是基本类型就添加到 cloneObj
cloneObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key];
}
}
return cloneObj;
}
const personDeep1 = deepClone(person);