ホームページ > 記事 > ウェブフロントエンド > JSのディープコピーとシャローコピーとは何ですか、そしてそれらを実装する方法
今日はJSのディープコピーとシャローコピーの違いとその機能について説明します。以下に例を示します。
var m = { a: 10, b: 20 }var n = m;n.a = 15;//このときの m.a の値は何ですか?
m.a は浅いコピーなので 15 を出力します。 n と m が指すのは同じヒープであり、オブジェクトのコピーはコピーされたオブジェクトの単なる参照です。
ディープコピー
ディープコピーは上記の浅いコピーとは異なり、オブジェクトの参照をコピーするのではなく、オブジェクトを完全にコピーします。たとえば、前の例と同様に、次のように記述します。
var m = { a: 10, b: 20 }var n = {a:m.a,b:m.b};n.a = 15;
今度は、m.a を再度出力してみると、m.a の値はまだ 10 であり、まだ 10 になっていないことがわかります。 m オブジェクトと n オブジェクトはすべて同じ値ですが、ヒープ内では対応するものは同じではありません。これはディープコピーです。
深いコピーと浅いコピー
深いコピーと浅いコピーの図はおおよそ次のとおりです:
浅いコピーは、オブジェクト自体ではなく、オブジェクトへのポインターをコピーするだけです。古いオブジェクトと新しいオブジェクトは依然として共有します。同じ記憶。ただし、ディープ コピーでは同一のオブジェクトが作成されます。新しいオブジェクトは元のオブジェクトとメモリを共有しないため、新しいオブジェクトを変更しても元のオブジェクトは変更されません。
浅いコピーの実装方法
1. 単純な代入によって実装できます
もちろん、次のように単純な関数をカプセル化することもできます:
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); console.log(cloneObj.c); console.log(cloneObj.d); cloneObj.b.a = "changed"; cloneObj.c = [1, 2, 3]; cloneObj.d = function() { alert("changed"); }; console.log(obj.b); console.log(obj.c); console.log(obj.d);
2、Object.assign () 実装
Object.assign() メソッドは、ソース オブジェクト独自の列挙可能なプロパティを任意の数でターゲット オブジェクトにコピーし、ターゲット オブジェクトを返すことができます。ただし、Object.assign() は浅いコピーを実行し、オブジェクト自体ではなく、オブジェクトのプロパティへの参照をコピーします。
var obj = { a: {a: "こんにちは", b: 21} };var initalObj = Object.assign({}, obj); initalObj.a.a = "変更されました";console.log(obj.a.a) ; // "変更されました"
注: オブジェクトにレイヤーが 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 }
ディープ コピーの実装方法
1. 方法 1 は手動でコピーすることです
上記の例 同様に、手動コピーでもディープコピーを実現できます。
2. オブジェクトにレイヤーが 1 つしかない場合は、上記の Object.assign() 関数を使用できます。
3. JSON に変換してから元に戻す
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);// falseconsole.log(obj1.body === obj2.body);// false
JSON.stringify を使用してオブジェクトを string に変換します。次に、JSON を使用して文字列を新しいオブジェクトに変換します。
次の関数をカプセル化できます
var cloneObj = function(obj){ var str, newobj = obj.constructor === Array ? [] : {}; if(typeof obj !== 'object'){ return; } else if(window.JSON){ str = JSON.stringify(obj), //系列化对象 newobj = JSON.parse(str); //还原 } else { for(var i in obj){ newobj[i] = typeof obj[i] === 'object' ? cloneObj(obj[i]) : obj[i]; } } return newobj;};
4. 再帰コピー
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);
5. Object.create() メソッドを使用します
ディープ コピーの効果を実現するには、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;}
6. jquery
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
7. lodash
もう 1 つの非常に人気のある関数ライブラリである lodash も、ディープ コピー用の _.cloneDeep を提供します。
var _ = require('lodash');var obj1 = { a: 1, b: { f: { g: 1 } }, c: [1, 2, 3]};var obj2 = _.cloneDeep(obj1);console.log(obj1.b.f === obj2.b.f);// false
これはパフォーマンスが良く、非常に使いやすいです。
これらの事例を読んだ後は、その方法を習得したと思います。さらに興味深い情報については、php 中国語 Web サイトの他の関連記事に注目してください。
関連書籍:
HTMLのテキストの最後の行が不完全に表示される場合の対処方法
以上がJSのディープコピーとシャローコピーとは何ですか、そしてそれらを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。