浅拷贝
1. let clone = {...target } 用扩展运算符 targer = { xxxx: xxx }
2.
function clone(target) {
let cloneTarget = {};
for (const key in target) {
cloneTarget[key] = target[key];
}
return cloneTarget;
};
深拷贝
function deepClone (target, map = new WeakMap()) { // 额外开辟一个存储空间WeakMap来存储当前对象
if (target === null) return target // 解决了null问题
if (target instanceof Date) return new Date(target) // 解决了 Date对象问题
if (target instanceof RegExp) return new RegExp(target) //解决了正则问题
if(!(target instanceof Object) ) return target //到这里,就剩下数组和对象还没解决。
if (typeof target !== 'object') return target // 如果是基本数据类型就返回
const cloneTarget = new target.constructor() //解决了数组问题 此时,cloneTarget 为[] 或 {}
if (map.get(target)) return map.get(target) // 当需要拷贝当前对象时,先去存储空间中找,如果有
的话直接返回
map.set(target, cloneTarget) // 如果存储空间中没有就存进 hash 里 解决了循环引用问题
Reflect.ownKeys(target).forEach(key => { // Reflect.ownKeys()解决了Symbol问题
cloneTarget[key] = deepClone(target[key], map) // 递归拷贝每一层
})
return cloneTarget
}
如何背下来,这个深拷贝函数?
解决了 日期 正则 数组 Null Symbol 循环引用
function deepClone (target,hash = new WeakMap()){
1. 先判断 时间 正则 和 null 如果是,返回它
2. 判断是不是对象(不是对象就剩普通属性了),如果不是,返回target
3. 这里要背 循环引用的两句,和中间插一句,用于解决 数组问题。
3.1 如果hash里面target键值对有值,就返回target的值
if (hash.get(target))return hash.get(target)
3.2 返回一个对象或者数组
let cloneTarget = new target.constructor ()
3.3 把cloneTarget 赋值给 hash里面的target键
4. 这里解决symbol问题,同时forEach遍历target对象,参数区域为 一个箭头函数,里面涉及到了
克隆对象 = deepClone( 当前对象 ,hash)
5. 返回克隆对象 cloneTarget
( key )=>{ cloneTarget [ key ] = deepClone( Target [ key ] , hash ) }
}
JSON.sringify 和 JSON.parse (深拷贝 )
JSON.parse(JSON.sringify(obj))
缺点: 不能正确拷贝 数组 日期 正则 函数等 (能拷贝数组)
.如果obj里有函数,undefined,则序列化的结果会把函数或 undefined丢失;
Object . assign(obj) 常用于react 的 reducer 赋值
缺点: 能拷贝数组,但不能拷贝深层对象属性,属于是没用。
常见的 递归方式
module.exports = function clone(target) {
if (typeof target === 'object') {
let cloneTarget = Array.isArray(target) ? [] : {};
for (const key in target) {
cloneTarget[key] = clone(target[key]);
}
return cloneTarget;
} else {
return target;
}
};