实现一个深拷贝,包括 Symbol 类型及 Regexp(正则)的拷贝
- 初级版
// 数据类型
let target = {
field1: 1,
field2: undefined,
field3: 'field3',
field4: {
child1: {
_child1: 1
},
child2: '2'
}
};
// 代码实现
function deepClone(target) {
if (Object.prototype.toString.call(target) == '[object Object]') {
let cloneTarget = {};
Object.keys(target).forEach(key => {
const item = target[key];
cloneTarget[key] = deepClone(item);
});
return cloneTarget;
}
return target;
}
- 终极版:可处理循环引用
// 数据类型
let target = {
field1: 1,
field2: undefined,
field3: 'field3',
field4: {
child1: {
_child1: 1
},
child2: '2'
}
};
target.target = target;
function deepClone(target, map = new WeakMap()) {
if (
Object.prototype.toString.call(target) == '[object Object]' ||
Object.prototype.toString.call(target) == '[object Array]'
) {
let cloneTarget = Object.prototype.toString.call(target) == '[object Object]' ? {} : [];
if (map.get(target)) {
return target;
}
map.set(target, cloneTarget);
Object.keys(target).forEach(key => {
const item = target[key];
cloneTarget[key] = deepClone(item, map);
});
return cloneTarget;
}
return target;
}
- 把 forEach 转换为 性能更好的 while
function _forEach(array, fn) {
let index = -1,
len = array.length;
while (++index < len) {
fn(array[index], index, array);
}
}
function deepClone(target, map = new WeakMap()) {
if (
Object.prototype.toString.call(target) == '[object Object]' ||
Object.prototype.toString.call(target) == '[object Array]'
) {
let cloneTarget = Object.prototype.toString.call(target) == '[object Object]' ? {} : [];
if (map.get(target)) {
return target;
}
map.set(target, cloneTarget);
_forEach(Object.keys(target), key => {
const item = target[key];
cloneTarget[key] = deepClone(item, map);
});
return cloneTarget;
}
return target;
}
究极版
let target = {
field1: 1,
field2: undefined,
field3: 'field3',
field4: {
child1: {
_child1: 1
},
child2: '2'
},
field4: [1, 2, 3],
reg: /\w*$/g
};
target.target = target;
let TAG_MAP_FUN = {};
function setTagsMap() {
['Set', 'Map', 'Object', 'Array', 'Function', 'RegExp', 'Symbol'].forEach(key => {
TAG_MAP_FUN['is' + key] = function () {
return Object.prototype.toString.call(arguments[0]) == `[object ${key}]`;
};
});
}
setTagsMap();
// 引用类型 和 null 的 typeof 都为 object
function isReference(target) {
const type = typeof target;
return target !== null && (type === 'object' || type === 'function');
}
function getInit(target) {
const Cons = target.constructor;
return new Cons();
}
function deepClone(target, map = new WeakMap()) {
if (TAG_MAP_FUN.isRegExp(target)) {
let newTarget = target.constructor(target.source, /\w*$/.exec(target));
newTarget.lastIndex = target.lastIndex;
return newTarget;
}
if (!isReference(target) || TAG_MAP_FUN.isFunction(target)) {
return target;
}
// 引用类型
let cloneTarget = getInit(target);
// 放置引用类型循环引用
if (map.get(target)) {
return target;
}
map.set(target, cloneTarget);
if (TAG_MAP_FUN.isSet(target)) {
target.forEach(value => {
cloneTarget.add(deepClone(value, map));
});
}
if (TAG_MAP_FUN.isMap(target)) {
target.forEach((value, key) => {
cloneTarget.set(key, deepClone(value, map));
});
}
if (TAG_MAP_FUN.isObject(target) || TAG_MAP_FUN.isArray(target)) {
Object.keys(target).forEach(key => {
const value = target[key];
cloneTarget[key] = deepClone(value, map);
});
}
return cloneTarget;
}
let newTarget = deepClone(target);
网友评论