s011-手写深拷贝★★
深拷贝方法
1.JSON.stringify() 和 JSON.parse()
3.手写简易版deepClone
function deepClone(obj) {
let newObj = obj.intanceof(Array) ? [] : {}
for(let item in obj) {
let template = typeof(obj[item]) == 'Object' ? deepClone(obj[item]) : obj[item]
newObj.item = template
}
return newObj;
}
版本2
function deepClone(obj = {}) {
if(typeof obj !== 'object' || obj == null) {
return obj
}
let result = obj.intanceof(Array) ? [] : {}
for(let key in obj) {
//保证key 不是原型上的属性
if(obj.hasOwnProperty(key)) {
result[key] = deepClone(obj[key])
}
}
return result;
}
项目中用的
// 深度克隆
export function deepClone(obj) {
let isArr = Array.isArray(obj);
let isJson = Object.prototype.toString.call(obj) === "[object Object]";
if (isArr) {
let newObj = [];
for (let i = 0; i < obj.length; i++) {
newObj[i] = deepClone(obj[i]);
}
return newObj;
} else if (isJson) {
let newObj = {};
for (let i in obj) {
newObj[i] = deepClone(obj[i]);
}
return newObj;
}
return obj;
}
function structuralClone(obj) {
return new Notification('', {data: obj, silent: true}).data;
}
const obj = /* ... */;
const clone = structuralClone(obj);
深拷贝(考虑到复制 Symbol 类型)
function isObject(val) {
return typeof val === "object" && val !== null;
}
function deepClone(obj, hash = new WeakMap()) {
if (!isObject(obj)) return obj;
if (hash.has(obj)) {
return hash.get(obj);
}
let target = Array.isArray(obj) ? [] : {};
hash.set(obj, target);
Reflect.ownKeys(obj).forEach((item) => {
if (isObject(obj[item])) {
target[item] = deepClone(obj[item], hash);
} else {
target[item] = obj[item];
}
});
return target;
}
深拷贝 structuredClone()
JavaScript 内置了一个 structuredClone() 的方法, 此方法提供了一种简单有效的方法来深度克隆对象, 且适用于大多数现代浏览器和 Node.js v17 以上
// 将原始对象传递给该函数, 它将返回一个具有不同引用和对象属性引用的深层副本
const obj = { name: 'Mike', friends: [{ name: 'Sam' }] };
const clonedObj = structuredClone(obj);
console.log(obj === clonedObj); // false
console.log(obj.friends === clonedObj.friends); // false
与众所周知的 JSON.parse(JSON.stringify())” 不同, structuredClone() 允许您克隆循环引用,这是目前在 JavaScript 中使用深拷贝最简单的方法。
兼容多种对象的神拷贝
function deepClone (target, hash = new WeakMap()) { // 额外开辟一个存储空间WeakMap来存储当前对象
if (target === null) return target // 如果是 null 就不进行拷贝操作
if (target instanceof Date) return new Date(target) // 处理日期
if (target instanceof RegExp) return new RegExp(target) // 处理正则
if (target instanceof HTMLElement) return target // 处理 DOM元素
if (typeof target !== 'object') return target // 处理原始类型和函数 不需要深拷贝,直接返回
// 是引用类型的话就要进行深拷贝
if (hash.get(target)) return hash.get(target) // 当需要拷贝当前对象时,先去存储空间中找,如果有的话直接返回
const cloneTarget = new target.constructor() // 创建一个新的克隆对象或克隆数组
hash.set(target, cloneTarget) // 如果存储空间中没有就存进 hash 里
Reflect.ownKeys(target).forEach(key => { // 引入 Reflect.ownKeys,处理 Symbol 作为键名的情况
cloneTarget[key] = deepClone(target[key], hash) // 递归拷贝每一层
})
return cloneTarget // 返回克隆的对象
}