この記事でわかることは、jsにおける浅いコピーと深いコピーの実装方法とは何なのかということです。 (要約) 必要な友人が参考になれば幸いです。
js には、string、number、boolean、null、undefind の 5 つの基本データ型があります。これら 5 種類の割り当ては値の転送です。オブジェクトの割り当ては、オブジェクト アドレスへの参照を割り当てることです。このとき、オブジェクト内のプロパティまたは値を変更すると、オブジェクトへのすべての参照の値が変更されます。オブジェクトへの参照をコピーするのではなく、実際に新しいオブジェクトをコピーしたい場合は、オブジェクトのディープ コピーを使用する必要があります。
あまり言う必要はありませんが、最も基本的な代入方法は、単にオブジェクトへの参照を割り当てることです。
Object.assign は ES6 の新しい関数です。 Object.assign() メソッドは、ソース オブジェクト自体の列挙可能なプロパティを任意の数だけターゲット オブジェクトにコピーし、ターゲット オブジェクトを返すことができます。ただし、Object.assign() は浅いコピーを実行し、オブジェクト自体ではなく、オブジェクトのプロパティへの参照をコピーします。
Object.assign(target, ...sources)
パラメータ:
target: ターゲット オブジェクト。
sources: 任意の数のソース オブジェクト。
戻り値: 対象のオブジェクトが返されます。
var obj = { a: {a: "hello", b: 21} }; var initalObj = Object.assign({}, obj); initalObj.a.a = "changed"; console.log(obj.a.a); // "changed"
次のことに注意してください:
Object.assign() は、次のように 1 つのレイヤーのディープ コピーを処理できます:
var obj1 = { a: 10, b: 20, c: 30 }; var obj2 = Object.assign({}, obj1); obj2.b = 100; console.log(obj1); // { a: 10, b: 20, c: 30 } <-- 沒被改到 console.log(obj2); // { a: 10, b: 100, c: 30 }
var obj1 = { a: 10, b: 20, c: 30 }; var obj2 = { a: obj1.a, b: obj1.b, c: obj1.c }; obj2.b = 100; console.log(obj1); // { a: 10, b: 20, c: 30 } <-- 沒被改到 console.log(obj2); // { a: 10, b: 100, c: 30 }
JSON.stringify を使用してオブジェクトを文字列に変換し、JSON.parse を使用して文字列を新しいオブジェクトに変換します。
var obj1 = { body: { a: 10 } }; var obj2 = JSON.parse(JSON.stringify(obj1)); obj2.body.a = 20; console.log(obj1); // { body: { a: 10 } } <-- 沒被改到 console.log(obj2); // { body: { a: 20 } } console.log(obj1 === obj2); // false console.log(obj1.body === obj2.body); // false
これは真のディープ コピーです。この方法はシンプルで使いやすいです。
しかし、このメソッドには、オブジェクトのコンストラクターが破棄されるなど、多くの欠点もあります。つまり、ディープ コピー後は、オブジェクトの元のコンストラクターが何であっても、ディープ コピー後はオブジェクトになります。
このメソッドが正しく処理できるオブジェクトは、Number、String、Boolean、Array、およびフラット オブジェクト、つまり、json で直接表現できるデータ構造のみです。 RegExp オブジェクトをこの方法でディープ コピーすることはできません。
つまり、この方法で使用できるのは JSON 形式に変換できるオブジェクトのみです。関数は JSON に変換できません。
var obj1 = { fun: function(){ console.log(123) } }; var obj2 = JSON.parse(JSON.stringify(obj1)); console.log(typeof obj1.fun); // 'function' console.log(typeof obj2.fun); // 'undefined' <-- 没复制
function deepClone(initalObj, finalObj) { var obj = finalObj || {}; for (var i in initalObj) { var prop = initalObj[i]; // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况 if(prop === obj) { continue; } if (typeof prop === 'object') { obj[i] = (prop.constructor === Array) ? [] : {}; arguments.callee(prop, obj[i]); } else { obj[i] = prop; } } return obj; } var str = {}; var obj = { a: {a: "hello", b: 21} }; deepClone(obj, str); console.log(str.a);
ディープ コピー効果を実現するには、var newObj = Object.create(oldObj) を直接使用します。 。
function deepClone(initalObj, finalObj) { var obj = finalObj || {}; for (var i in initalObj) { var prop = initalObj[i]; // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况 if(prop === obj) { continue; } if (typeof prop === 'object') { obj[i] = (prop.constructor === Array) ? [] : Object.create(prop); } else { obj[i] = prop; } } return obj; }
jquery は、ディープ コピーに使用できる $.extend を提供します。
var $ = require('jquery'); var obj1 = { a: 1, b: { f: { g: 1 } }, c: [1, 2, 3] }; var obj2 = $.extend(true, {}, obj1); console.log(obj1.b.f === obj2.b.f); // false
lodash など、ディープ コピー関数を備えた他のサードパーティ関数ライブラリもあります。
以上がjsでの浅いコピーと深いコピーの実装方法は何ですか? (要約)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。