直接上コード:
/**
* JSON.parse(JSON.stringify(object))の問題は
* 1、undefinedを無視すること
* 2、Symbolを無視すること
* 3、関数をシリアライズできないこと
* 4、循環参照オブジェクトを解決できないこと
* DeepClone1 -> タイプの問題を解決する、配列を含む
* @param target
*/
export function DeepClone1(target) {
if (typeof target === 'object') {
// 配列かどうかを考慮する
let cloneTarget = Array.isArray(target) ? [] : {};
for (const key in target) {
// プロトタイププロパティを考慮しない
if (target.hasOwnProperty(key)) {
// 再帰的にコピーする
cloneTarget[key] = DeepClone1(target[key]);
}
}
return cloneTarget;
// 非参照型、直接返すだけ
} else {
return target;
}
}
/**
* 循環参照の問題を解決する、mapの代わりにweakMapを使用し、メモリ解放する
* mapは追加のメモリスペースを確保し、現在のオブジェクトとコピーされたオブジェクトの関係を保存する
*/
export function DeepClone2(target, map = new Map()) {
if (typeof target === 'object') {
let cloneTarget = Array.isArray(target) ? [] : {};
if (map.get(target)) {
return map.get(target);
}
map.set(target, cloneTarget);
for (const key in target) {
if (target.hasOwnProperty(key)) {
cloneTarget[key] = DeepClone2(target[key], map);
}
}
return cloneTarget;
} else {
return target;
}
}
// オブジェクトと関数以外にも、参照型にはnullとfunctionもあり、isObjectをラップできる
function isObject(target) {
const type = typeof target;
return target !== null && (type === 'object' || type === 'function');
}
/**
* 可遍歴かどうかに基づいて、データ型を分類して処理する
* 可遍歴:object/array/map/set
* 不可遍歴:string/number/boolean/symbol、undefined/null、function、regex/date/error/math/JSON
* 返す [object Array]
*/
function getType(target) {
return Object.prototype.toString.call(target);
}
// 関数型は直接返す、一般的に考慮しない