5. 深拷贝
小于 1 分钟
5. 深拷贝
浅拷贝:
/* eslint-disable no-prototype-builtins */
export function shallowCopy(obj) {
if (typeof obj !== 'object')
return
const newObj = Array.isArray(obj) ? [] : {}
for (const key in obj) {
if (obj.hasOwnProperty(key))
newObj[key] = obj[key]
}
return newObj
简单的深拷贝,只考虑普通对象属性,不考虑内置对象和函数,不能解决循环引用问题:
export function deepClone(obj) {
if (typeof obj !== 'object')
return
const newObj = Array.isArray(obj) ? [] : {}
for (const key in obj) {
if (obj.hasOwnProperty(key))
newObj[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]
}
return newObj
复杂版深拷贝:基于简单版的基础上,还考虑了内置对象比如 Date
、RegExp
等对象和函数以及解决了循环引用的问题:
/* eslint-disable no-prototype-builtins */
const isObject = target => (typeof target === 'object' || typeof target === 'function') && target !== null
export function deepClone(target, map = new WeakMap()) {
if (map.get(target))
return target
// 获取当前值的构造函数:获取它的类型
const constructor = target.constructor
// 检测当前对象 target 是否与正则、日期格式对象匹配
if (/^(RegExp|Date)$/i.test(constructor.name)) {
// 创建一个新的特殊对象(正则类/日期类)的实例
return new constructor(target)
}
if (isObject(target)) {
map.set(target, true) // 为循环引用的对象做标记
const cloneTarget = Array.isArray(target) ? [] : {}
for (const prop in target) {
if (target.hasOwnProperty(prop))
cloneTarget[prop] = deepClone(target[prop], map)
}
return cloneTarget
}
else {
return target
}
}