0%
深度克隆
- 传统做法 最通用,最易扩展
- JSON 有缺陷:
- Map、Functoin 会被丢弃。
- 递归会报错。
- 通信 MessageChannel 有缺陷:
- 异步
- 限制在浏览器环境中
传统做法
javascript
const cache = new WeakMap()
function deepClone(value) {
// 原始类型不需要克隆
if (type value !== 'object' || value === null) {
return value
}
/**
* 按具体需求,扩充类型
*/
// 处理循环引用
if (cache.has(value)) {
return cache.get(value)
}
const result = Array.isArray(value) ? [] : {}
// 处理类和对象
Object.setPrototypeOf(result, Object, getPrototypeOf(value))
// 处理循环引用
cache.set(value, result)
for (let key in value) {
/**
* 判断是否是自有属性,避免把类中的属性克隆进去
* 只克隆对象上的属性
*/
if (!value.hasOwnProperty(key)) {
result[key] = deepClone(value[key])
}
}
return result
}
javascript
class Test {
constructor() {
this.a = 1
this.b = 2
}
c() {
console.log('c')
}
}
const obj = new Test()
Test.prototype.d = 1
objh = obj
console.log(obj)
console.log(deepClone(obj))
下面的函数是从狗袋那复制来的
javascript
/**
* @description 深拷贝函数
* @param {Object} obj 要拷贝的对象
*/
function deepClone(obj = {}, map = new WeakMap()) {
if (typeof obj !== 'object' || obj == null) {
// obj不是对象或者数组,直接返回
return obj
}
// 防止循环引用
if (map.has(obj)) {
return map.get(obj)
}
// 初始化返回结果
let result
if (obj instanceof Array) {
result = []
} else {
result = {}
}
map.set(obj, result);
for (let key in obj) {
// 保证key不是原型的属性
if (obj.hasOwnProperty(key)){
// 递归
result[key] = deepClone(obj[key], map)
}
}
// 返回结果
return result
}