Heim > Artikel > Web-Frontend > Ein tiefgreifendes Verständnis von Shallow Copy und Deep Copy in JavaScript
Der Inhalt dieses Artikels befasst sich mit einem tiefgreifenden Verständnis von Shallow Copy und Deep Copy. Jetzt kann ich ihn mit allen teilen, die ihn brauchen.
Es gibt einige Grundtypen in JS wie Number
, String
, Boolean,
und Objekte sind wie folgt: { Name: 'Larry', Skill: 'Node.js' }, Objekte und Grundtypen sind Der größte Unterschied liegt in der Art und Weise, wie sie Werte übergeben. Der Grundtyp von
wird wie folgt als Wert übergeben: Beim Ändern von a
wird er nicht in b
var a = 25; var b = a; b = 18; console.log(a);//25 console.log(b);//18
geändert. Das Objekt ist jedoch anders Objekt wird als Wert übergeben:
var obj1 = { a: 10, b: 20, c: 30 }; var obj2 = obj1; obj2.b = 100; console.log(obj1); // { a: 10, b: 100, c: 30 } <-- b 被改到了 console.log(obj2); // { a: 10, b: 100, c: 30 }
Kopieren Sie eine Kopie von obj1
und nennen Sie sie obj2,
und ändern Sie dann obj2.b
in 100,
, ändern Sie es jedoch versehentlich in obj1.b,
weil es sich im Grunde um dasselbe Objekt handelt. Dies wird als flache Kopie bezeichnet.
Um solche Fehler zu vermeiden, schreiben Sie wie folgt:
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 } <-- b 沒被改到 console.log(obj2); // { a: 10, b: 100, c: 30 }
Dies ist eine tiefe Kopie und wird nicht am Original verändert obj1。
Shallow Copy kopiert nur den Zeiger auf ein Objekt, ohne das Objekt selbst, das Alte und das Neue zu kopieren Objekte teilen sich immer noch den gleichen Speicher. Durch eine tiefe Kopie wird jedoch ein identisches Objekt erstellt. Das neue Objekt teilt sich den Speicher nicht mit dem Originalobjekt, und Änderungen am neuen Objekt führen nicht zu einer Änderung des Originalobjekts.
ist einfach das Kopieren
1. Kopieren Sie einfach die Aussage
<script type="text/javascript"> 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); </script>
Das Ergebnis ist:
2. Object.assign()
<code>Object.assign
Ja Neue Funktionen in ES6. Die Methode Object.assign() kann eine beliebige Anzahl der aufzählbaren Eigenschaften des Quellobjekts in das Zielobjekt kopieren und dann das Zielobjekt zurückgeben. Aber <code>Object.assign()<code>Object.assign() führt eine flache Kopie durch und kopiert Verweise auf die Eigenschaften des Objekts, nicht das Objekt selbst.
Object.assign(target, ...sources)
Parameter:
Ziel: Zielobjekt.
Quellen: beliebig viele Quellobjekte.
Rückgabewert: Das Zielobjekt wird zurückgegeben.
var obj = { a: {a: "hello", b: 21} }; var initalObj = Object.assign({}, obj); initalObj.a.a = "changed"; console.log(obj.a.a); // "changed"
Kompatibilität:
Hinweis:
Object.assign()可以处理一层的深度拷贝,如下:
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 }
Wenn Sie das Originalobjekt vollständig kopieren möchten, müssen Sie Deep Copy verwenden. Hier stellen wir verschiedene Deep Copy-Methoden vor.
1. Manuelles Kopieren
Kopieren Sie die Eigenschaften eines Objekts in die Eigenschaften eines anderen Objekts
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 }
Aber das ist sehr mühsam, Sie Ein Man muss sich selbst kopieren; und diese Art kann nicht als Deep Copy betrachtet werden, da es auch Objekte innerhalb des Objekts geben kann, wie zum Beispiel die folgende Situation:
var obj1 = { body: { a: 10 } }; var obj2 = { body: obj1.body }; obj2.body.a = 20; console.log(obj1); // { body: { a: 20 } } <-- 被改到了 console.log(obj2); // { body: { a: 20 } } console.log(obj1 === obj2); // false console.log(obj1.body === obj2.body); // true
Obwohl obj1
und obj2 <code>obj2
sind unterschiedliche Objekte, aber sie haben denselben obj1.body<code>obj1.body
, <code>,
. Wenn Sie also obj2.body.a<code>obj2.body.a
ändern, wird dies auch beim alten der Fall sein geändert werden.
2. Wenn das Objekt nur eine Ebene hat, können Sie Folgendes verwenden: Objekt<code class=" language-js">Object<span class="token punctuation">.<span class="token function">assign()函数</span></span>
.zuordnen () Funktion
<code>Object.assign({}, obj1)obj1
obj2
<code>Object.assign({}, obj1)<code>obj1 bedeutet, zuerst ein leeres Objekt {} zu erstellen, und Weisen Sie dann obj2.b
Kopieren Sie alle Attribute in obj1。
zu, sodass obj2
hat zu diesem Zeitpunkt keine Auswirkungen auf
genauso aussieht wie
. Das Ändern von <code>Object.assign
weil Object .assign<strong> den gleichen Effekt wie unser manuelles Kopieren hat, es also nur Objekte mit nur einer Tiefenebene verarbeiten kann und es keine Möglichkeit gibt, echtes Deep Copy zu erreichen. Sie können die Verwendung jedoch in Betracht ziehen, wenn nur eine Objektebene kopiert werden soll. <span class="token punctuation"></span></strong>
3. Konvertieren Sie in JSON und dann wieder zurück JSON.stringify
JSON.parse
JSON.stringify<pre class="brush:php;toolbar:false;">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</pre> zu Konvertieren Sie das Objekt. Konvertieren Sie es in eine Zeichenfolge und konvertieren Sie die Zeichenfolge dann mit <code>JSON.parse<p> in ein neues Objekt. <span style="line-height: 1.5;"></span><br></p>Das ist echtes Deep Copy, <p>Diese Methode ist einfach und leicht anzuwenden. </p>
<p><code>Number, String, Boolean, Array, 扁平对象
Aber diese Methode hat auch viele Nachteile, zum Beispiel wird der Konstruktor des Objekts verworfen. Das heißt, nach dem tiefen Kopieren wird das Objekt unabhängig vom ursprünglichen Konstruktor des Objekts nach dem tiefen Kopieren zum Objekt. JSON
Die einzigen Objekte, die diese Methode korrekt verarbeiten kann, sind Number-, String-, Boolean-, Array- und flache Objekte<code>function
, also jene Datenstrukturen, die direkt durch JSON dargestellt werden können. RegExp-Objekte können auf diese Weise nicht tief kopiert werden. JSON。
JSON-Format konvertiert werden können. Beispielsweise kann <code>function nicht in <code>JSON konvertiert werden . <pre class="brush:php;toolbar:false;">var obj1 = { fun: function(){ console.log(123) } };
var obj2 = JSON.parse(JSON.stringify(obj1));
console.log(typeof obj1.fun);
// &#39;function&#39;
console.log(typeof obj2.fun);
// &#39;undefined&#39; <-- 没复制</pre><p>要复制的<code>function
会直接消失,所以这个方法只能用在单纯只有数据的对象。
4、递归拷贝
function deepClone(initalObj, finalObj) { var obj = finalObj || {}; for (var i in initalObj) { if (typeof initalObj[i] === 'object') { obj[i] = (initalObj[i].constructor === Array) ? [] : {}; arguments.callee(initalObj[i], obj[i]); } else { obj[i] = initalObj[i]; } } return obj; }var str = {};var obj = { a: {a: "hello", b: 21} }; deepClone(obj, str); console.log(str.a);
上述代码确实可以实现深拷贝。但是当遇到两个互相引用的对象,会出现死循环的情况。
为了避免相互引用的对象导致死循环的情况,则应该在遍历的时候判断是否相互引用对象,如果是则退出循环。
改进版代码如下:
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
可以用来做 Deep Copy。
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
另外一个很热门的函数库lodash,也有提供_.cloneDeep
用来做 Deep Copy。
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
这个性能还不错,使用起来也很简单。
参考:
Das obige ist der detaillierte Inhalt vonEin tiefgreifendes Verständnis von Shallow Copy und Deep Copy in JavaScript. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!