blog

フロントエンドの開発シリーズ120 - deepCloneの高度な部分

コピーつまり、コピー(コピー|クローン)、指定されたデータのコピーを取得する動作は、理論的には、NULL、未定義、文字列、数値、ブール値、オブジェクト、関数、配列、正規のテーブルを含むがこれらに限定さ...

Jan 5, 2024 · 3 min. read
シェア
データコピーは、シャローコピーシャローコピーに分けることができます。浅いコピーは1つのレイヤーをコピーし、共有の問題が発生する可能性がありますが、深いコピーは複数のレイヤーをコピーし、得られるコピーには共有の問題はありません。

データをコピーする方法は、ループや 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 を使用したディープコピーの実装は完璧ではありません。以下は、再帰を使用したディープコピーの完璧なソリューションです。

javascript
/* ディープコピーの実装関数 */

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));
Read next

効率化自助道:非効率的な会議にはノーと言いましょう!

会議が多すぎることが効率に影響を与える要因の一つであるとすれば、「会議を減らす」ことはチームの効率を向上させるための正しい薬なのでしょうか?また、実際にどのように実践すべきなのでしょうか?

Jan 4, 2024 · 6 min read