-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
手写题:深拷贝 #11
Labels
Comments
基于洪佬的深拷贝自己又实现了一遍,增加了 function deepClone(originValue) {
/**
* 1.function、undefined、RegExp不会被解析
* 2.循环引用会抛出错误
* 如不考虑上述情况则可以使用此方法
*/
return JSON.parse(JSON.stringify(originValue));
}
/**
* 举个栗子:循环引用问题
* const obj = {};
* obj.obj = obj;
* deepClone(obj); // Uncaught TypeError: Converting circular structure to JSON
*/
/**
* @description:
* @param {*} originValue 源数据
* @param { WeakMap } map 便于处理循环引用问题
* @return {*} 深拷贝后的数据
*/
function deepClone(originValue, map = new WeakMap()) {
// 判断如果是 Symbol 的 value, 那么创建一个新的 Symbol
if (typeof originValue === "symbol") {
return Symbol(originValue.description);
}
// null、function、Date、简单数据类型则直接返回
if (originValue === null || originValue instanceof Date || typeof originValue !== "object") {
return originValue;
}
// 数据在weakMap中有引用则直接返回引用
if (map.has(originValue)) {
return map.get(originValue);
}
// 处理复杂数据类型Map、Set、Object、Array、RegExp
if (originValue instanceof RegExp) {
/**
* 正则需处理lastIndex, 举个🌰
* const reg = reg1 = /\d/g
* reg.exec('123')
* reg.lastIndex === reg1.lastIndex === 1 // true
*/
const newValue = new originValue.constructor(originValue.source, originValue.flags);
newValue.lastIndex = 0;
return newValue;
}
// 前提条件,原生数据类型或拥有正确的构造器
const bucket = new originValue.constructor();
map.set(originValue, bucket);
// 其余数据可以处理成可迭代类型, Reflect.ownKeys 相当于 Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))
const iterator = originValue.constructor === Object ? Reflect.ownKeys(originValue) : originValue;
// 特殊情况: RegExp.prototype.exec 返回的数组, 比平时的数组多出input跟index属性
if(Array.isArray(originValue) && originValue[0] && Object.prototype.hasOwnProperty.call(originValue, 'index')) {
bucket.index = originValue.index
bucket.input = originValue.input
}
for (const item of iterator) {
let [key, value] = [];
if (Array.isArray(item)) {
[key, value] = item;
} else if (originValue.constructor === Object) {
[key, value] = [item, originValue[item]];
} else {
value = item;
}
setValue(bucket, key, deepClone(value, map));
}
return bucket;
}
function setValue(origin, key, value) {
switch (origin.constructor) {
case Map:
return origin.set(key, value);
case Set:
return origin.add(value);
case Array:
return origin.push(value);
default:
origin[key] = value;
break;
}
} |
普通简单克隆 Source Code export function deepClone(origin: unknown): unknown {
if (isArray(origin)) return origin.map(child => deepClone(child))
if (isObject(origin)) {
return Object.fromEntries(
Object.entries(origin).map(([k, v]) => [k, deepClone(v)]),
)
}
return origin
} 避免循环引用 Source Code export function deepClone2(origin: any, hash = new WeakMap()): any {
if (isObject(origin)) {
if (hash.has(origin)) return hash.get(origin)
const target: any = isArray(origin) ? [] : {}
hash.set(origin, target)
Object.entries(origin).forEach(([k, v]: [string, any]) => {
if (isRegExp(v))
target[k] = new RegExp(v)
else if (isDate(v))
target[k] = new Date(v)
else
target[k] = deepClone2(v, hash)
})
return target
}
return origin
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The text was updated successfully, but these errors were encountered: