1.浅拷贝
一个浅拷贝的变量发生变化其他变量的值会随之改变。意思是没有多盖房子而是好多人都有房子的使用权。
浅拷贝场景:
1.等号赋值
let arr = [1, 2, 3, 4];
let newArr = arr;
2.标准内置对象赋值操作
2.深拷贝
反之,一个深拷贝的变量发生变化其他变量的值不会会随之改变。意思是一直在盖房子,一个人一个房子的使用权。
深拷贝方法
1.structuredClone(),缺点:浏览器兼容性不完全
const original = { name: "MDN" };
original.itself = original;
// Clone it
const clone = structuredClone(original);
2.手写深拷贝方法
function deepClone(o, map = new Map()) {
// console.log('map===,map', map);
const { isAble, value } = isAbleDeepClone(o)
// 如果不是可以深拷贝的参数 直接返回出去
if (!isAble) return value
// 判断参数是否循环引用 识别当前参数是否引用了
const key = map.get(o)
/*
如果拿到参数对应的value,也就是说原对象的key(当前递归参数),
指向了当前对象,出现了循环引用,直接return ,避免递归循环
*/
if (key) {
console.log('========出现循环引用=====');
return key
}
const target = new o.constructor(); // 创建被拷贝的对象实例---{}
map.set(o, target) // 每次set进去的key是参数o,value也是参数o
for (const k in o) {
target[k] = deepClone(o[k], map)
}
return target
}
// 判断是否是对象或者数组 保证深拷贝可以进行下去
function isAbleDeepClone(o) {
const typeStr = Object.prototype.toString.call(o)
if (typeStr === '[object Undefined]' || typeof o !== 'object') return { isAble: false, value: o }
if (typeStr === '[object Date]') return { isAble: false, value: new Date(o) }
if (typeStr === '[object RegExp]') return { isAble: false, value: new RegExp(o) }
if (typeStr === '[object Array]') return { isAble: true }
if (typeStr === '[object Object]') return { isAble: true }
}
3.JSON.stringify()
function cloneJson(o) {
/*
undefined、任意的函数以及 symbol 值,
在序列化过程中会被忽略(出现在非数组对象的属性值中时),
或者被转换成 null(出现在数组中时)。
函数、undefined 被单独转换时,会返回 undefined,
如:JSON.stringify(function(){}) or JSON.stringify(undefined).
*/
return JSON.parse(JSON.stringify(o))
}