关于javascript:深拷贝终结篇

42次阅读

共计 2221 个字符,预计需要花费 6 分钟才能阅读完成。

const getType = obj => Object.prototype.toString.call(obj);

const isObject = (target) => (typeof target === ‘object’ || typeof target === ‘function’) && target !== null;

const canTraverse = {
‘[object Map]’: true,
‘[object Set]’: true,
‘[object Array]’: true,
‘[object Object]’: true,
‘[object Arguments]’: true,
};
const mapTag = ‘[object Map]’;
const setTag = ‘[object Set]’;
const boolTag = ‘[object Boolean]’;
const numberTag = ‘[object Number]’;
const stringTag = ‘[object String]’;
const symbolTag = ‘[object Symbol]’;
const dateTag = ‘[object Date]’;
const errorTag = ‘[object Error]’;
const regexpTag = ‘[object RegExp]’;
const funcTag = ‘[object Function]’;

const handleRegExp = (target) => {
const {source, flags} = target;
return new target.constructor(source, flags);
}

const handleFunc = (func) => {
// 箭头函数间接返回本身
if(!func.prototype) return func;
const bodyReg = /(?<={)(.|n)+(?=})/m;
const paramReg = /(?<=().+(?=)s+{)/;
const funcString = func.toString();
// 别离匹配 函数参数 和 函数体
const param = paramReg.exec(funcString);
const body = bodyReg.exec(funcString);
if(!body) return null;
if (param) {

const paramArr = param[0].split(',');
return new Function(...paramArr, body[0]);

} else {

return new Function(body[0]);

}
}

const handleNotTraverse = (target, tag) => {
const Ctor = target.constructor;
switch(tag) {

case boolTag:
  return new Object(Boolean.prototype.valueOf.call(target));
case numberTag:
  return new Object(Number.prototype.valueOf.call(target));
case stringTag:
  return new Object(String.prototype.valueOf.call(target));
case symbolTag:
  return new Object(Symbol.prototype.valueOf.call(target));
case errorTag: 
case dateTag:
  return new Ctor(target);
case regexpTag:
  return handleRegExp(target);
case funcTag:
  return handleFunc(target);
default:
  return new Ctor(target);

}
}

const deepClone = (target, map = new WeakMap()) => {
if(!isObject(target))

return target;

let type = getType(target);
let cloneTarget;
if(!canTraverse[type]) {

// 解决不能遍历的对象
return handleNotTraverse(target, type);

}else {

// 这波操作相当要害,能够保障对象的原型不失落!let ctor = target.constructor;
cloneTarget = new ctor();

}

if(map.get(target))

return target;

map.set(target, true);

if(type === mapTag) {

// 解决 Map
target.forEach((item, key) => {cloneTarget.set(deepClone(key, map), deepClone(item, map));
})

}

if(type === setTag) {

// 解决 Set
target.forEach(item => {cloneTarget.add(deepClone(item, map));
})

}

// 解决数组和对象
for (let prop in target) {

if (target.hasOwnProperty(prop)) {cloneTarget[prop] = deepClone(target[prop], map);
}

}
return cloneTarget;
}

正文完
 0