データをコピーする方法は、ループや Object.assign() など、数多くありますが、これらはすべてシャローコピーです。 ディープコピーを実装する一般的な方法のひとつは、組み込みの JSON オブジェクトを使用してシリアライズとデシリアライズを行うことです。 以下のコードを参照してください。
address': Osaka',
'color': 'red'
}
};
var obj = JSON.parse(JSON.stringify(a));
a.info.address = 'Tokyo';
console.log(obj);まず、オブジェクトは JSON.stringify() メソッドを使用して JSON 文字列にシリアライズされ、その後、デシリアライズされて元のオブジェクトに戻されます。 このオブジェクトのコピー方法はクリーンで効率的ですが、1つの小さな欠点があります。残念ながら、JSONデータには関数や未定義の型が含まれないため、シリアライズの際にオブジェクト内のこの部分のデータは直接フィルタリングされてしまいます。さらに、通常のデータ型も空オブジェクトとして扱われます。
var b = {
'name': 'MiTaoEr',
'a': undefined,
'obj': function () {
},
'foo': /wen/,
'info': {
'address': '東京',
'color': 'red'
}
};
console.log(JSON.parse(JSON.stringify(b)));JSON を使用したディープコピーの実装は完璧ではありません。以下は、再帰を使用したディープコピーの完璧なソリューションです。
/* ディープコピーの実装関数 */ let deepClone = (val, wm = new WeakMap) => {
if (val == null) return val;
typeof val !== "object" であれば val を返します。
val が Date のインスタンスであれば、new Date(val) を返します。
val が RegExp のインスタンスであれば、new RegExp(val) を返します。
wm.has(val) が true であれば wm.get(val) を返します。
let _instance = new val.constructor;
wm.set(val, _instance);
for (let key in val) {
if (val.hasOwnProperty(key)) _instance[key] = deepClone(val[key], wm);
}
return _instance;
}_instanceは参照型のデータであるため、forループのその後の実行により、_instanceの内容が更新されます。 循環参照の問題を考慮し、deepCloneメソッドではWeakMap型を使用しています。 wm.setメソッドが実行された後にwmに格納されたデータがkey === valueとなります。 このオブジェクトは、データを記憶するために使用されます。
var a = {
'name': 'wen-ding-ding',
'obj': { 'id': 0x29a }
};
a.c = a;
var bar = deepClone(a);
console.log(a, bar);
console.log(a.c === bar.c, a.c === a);
a.obj.id = 0x378;
console.log(bar.obj.id);
var b = [
,
0x12c
];
var foo = deepClone(b);
b.push(0x190);
console.log(b, foo);
var B = new Date();
var Obj = deepClone(B);
console.log(B, Obj, B == Obj);
console.log(deepClone(null), deepClone(undefined));
var C = new RegExp(/\{\{(.+?)\}\}/);
var Foo = deepClone(C);
console.log(C, Foo, C == Foo);
console.log(deepClone('wen-ding-ding'), deepClone(0x7e3), deepClone(!false));




