JavaScript では、オブジェクトをコピーするのが一般的です。ただし、単純な copy ステートメントではオブジェクトの浅いコピーしか作成できません。つまり、参照されるオブジェクトではなく参照がコピーされます。多くの場合、元のオブジェクトが意図せずに変更されるのを防ぐために、オブジェクトのディープ コピーを作成する必要があります。
オブジェクトの深いコピーと浅いコピーの違いは次のとおりです:
浅いコピー: オブジェクト自体ではなく、オブジェクトの参照のみをコピーします。
深いコピー: によって参照されるすべてのオブジェクトをコピーします。コピーされたオブジェクト。
1. 浅いコピーの実装
浅いコピーの実装方法は、単純な copy ステートメントを使用する限り、比較的簡単です。
1.1 方法 1: 単純な copy ステートメント
/* ================ 浅拷贝 ================ */ function simpleClone(initalObj) { var obj = {}; for ( var i in initalObj) { obj[i] = initalObj[i]; } return obj; }
/* ================ 客户端调用 ================ */ var obj = { a: "hello", b: { a: "world", b: 21 }, c: ["Bob", "Tom", "Jenny"], d: function() { alert("hello world"); } } var cloneObj = simpleClone(obj); // 对象拷贝 console.log(cloneObj.b); // {a: "world", b: 21} console.log(cloneObj.c); // ["Bob", "Tom", "Jenny"] console.log(cloneObj.d); // function() { alert("hello world"); } // 修改拷贝后的对象 cloneObj.b.a = "changed"; cloneObj.c = [1, 2, 3]; cloneObj.d = function() { alert("changed"); }; console.log(obj.b); // {a: "changed", b: 21} // // 原对象所引用的对象被修改了 console.log(obj.c); // ["Bob", "Tom", "Jenny"] // 原对象所引用的对象未被修改 console.log(obj.d); // function() { alert("hello world"); } // 原对象所引用的函数未被修改
1.2 方法 2: Object.assign()
Object.assign() メソッドは、任意の数のソース オブジェクトを独自の列挙可能オブジェクトに割り当てることができます。ターゲット オブジェクトにコピーされてから、ターゲット オブジェクトに返されます。ただし、Object.assign() は浅いコピーを実行し、オブジェクト自体ではなく、オブジェクトのプロパティへの参照をコピーします。
var obj = { a: {a: "hello", b: 21} }; var initalObj = Object.assign({}, obj); initalObj.a.a = "changed"; console.log(obj.a.a); // "changed"
2. ディープ コピーの実装
ディープ コピーを実装するには、最も単純な JSON.parse() メソッド、一般的に使用される再帰コピー メソッド、ES5 の Object.create() メソッドなど、さまざまな方法があります。
2.1 方法 1: JSON.parse() メソッドを使用する
ディープ コピーを実装するには、さまざまな方法があります。たとえば、最も簡単な方法は、JSON.parse() を使用することです。シンプルで使いやすいです。
しかし、このメソッドには、オブジェクトのコンストラクターが破棄されるなど、多くの欠点もあります。つまり、ディープ コピー後は、オブジェクトの元のコンストラクターが何であっても、ディープ コピー後はオブジェクトになります。
このメソッドが正しく処理できる唯一のオブジェクトは、数値、文字列、ブール値、配列、およびフラット オブジェクト、つまり、json で直接表現できるデータ構造です。 RegExp オブジェクトをこの方法でディープ コピーすることはできません。
2.2 方法 2: 再帰コピーコードは次のとおりです:
上記のコードは確かにディープコピーを実現できます。ただし、相互に参照する 2 つのオブジェクトに遭遇すると、無限ループが発生します。
相互参照するオブジェクトによって引き起こされる無限ループを回避するには、トラバーサル中にオブジェクトが相互参照するかどうかを判断し、相互参照する場合はループを終了する必要があります。
改善されたコードは次のとおりです:
/* ================ 深拷贝 ================ */ function deepClone(initalObj) { var obj = {}; try { obj = JSON.parse(JSON.stringify(initalObj)); } return obj; }
ディープ コピーの効果を実現するには、var newObj = Object.create(oldObj) を直接使用します。
/* ================ 客户端调用 ================ */ var obj = { a: { a: "world", b: 21 } } var cloneObj = deepClone(obj); cloneObj.a.a = "changed"; console.log(obj.a.a); // "world"
3. 参考:jQuery.extend()メソッドの実装
jQuery.jsのjQuery.extend()もオブジェクトのディープコピーを実装します。参考までに公式コードを以下に掲載します。
公式リンクアドレス:
https://github.com/jquery/jquery/blob/master/src/core.js。