Heim >Web-Frontend >js-Tutorial >Eingehende Analyse von Objektkopiermethoden in JavaScript (mit Code)

Eingehende Analyse von Objektkopiermethoden in JavaScript (mit Code)

奋力向前
奋力向前nach vorne
2021-08-20 09:55:371947Durchsuche

Im vorherigen Artikel „Was Sie über die Verwendung von JavaScript „jquery inheritance“ wissen müssen (detaillierte Code-Erklärung) “ haben wir etwas über die Verwendung von JavaScript „jquery inheritance“ gelernt. Der folgende Artikel stellt Ihnen die Methode zum Kopieren von Objekten in JS vor. Freunde in Not können sich darauf beziehen.

Eingehende Analyse von Objektkopiermethoden in JavaScript (mit Code)

Apropos Objektkopieren in javascript: Das erste, woran wir denken, ist Object.assign()javascript中的对象拷贝,首先我们想到的是Object.assign()

JSON.parse(JSON.stringify()),还有ES6的展开操作符[...]

因为在js=运算符 对于对象来说,不能创建副本,只是对该对象的引用

运算符

var x = {
  a: 1,
  b: 2,
};
y = x;
x.a = 10;
console.log(x); //{a:10, b:2}
console.log(y); //{a:10, b:2}

所以在进行对象操作时,运算符等于号(=)不可取

Object.assign()

var x = {
  a: 1,
  b: 2,
};
y = Object.assign({}, x);
x.a = 10;
console.log(x); //{a:10, b:2}
console.log(y); //{a:1, b:2}

初看,不会发现异常,因为所要的就是我们所要的结果,把对象结构弄再稍微复杂些再看

var x = {
  a: 1,
  b: 2,
  c: {
    d: 3,
  },
};
y = Object.assign({}, x);

x.a = 5;
console.log(x); //{a:5, b:2, c:{d:3}}
console.log(y); //{a:5, b:2, c:{d:3}}

x.c.d = 10;
console.log(x); //{a:5, b:2, c:{d:10}}
console.log(y); //{a:5, b:2, c:{d:10}}

此时就发现坑了,那么已经证明了Object.assign()只是实现了对象的浅拷贝

Object.assign()还需要注意的一点是,原型链上属性的不可枚举对象是无法复制的,看一下代码:

var x = {
  a: 1,
};
var y = Object.create(x, {
  b: {
    value: 2,
  },
  c: {
    value: 3,
    enumerable: true,
  },
});
var z = Object.assign({}, y);
console.log(z); //{c:3}

拿到z的值很让人意外,因为xy的原型链,所以x不会被复制

属性b是不可枚举属性,也不会被复制

只有c具有可枚举描述,他可以被枚举,所以才能被复制

以上的坑也可以很好的被解决,且往下看: 

深拷贝JSON.parse(JSON.stringify())

解决浅拷贝的坑

var x = {
  a: 1,
  b: 2,
  c: {
    d: 3,
  },
};
y = JSON.parse(JSON.stringify(x));
x.a = 5;
x.c.d = 10;
console.log(x); //{a:5, b:2, c:{d:10}}
console.log(y); //{a:1, b:2, c:{d:3}}

当然普通的对象,此种复制方式已经是基本是完美了,那么他的坑在哪里呢

var x = {
  a: 1,
  b: function b() {
    return "2";
  },
};
y = JSON.parse(JSON.stringify(x));
z = Object.assign({}, x);

console.log(y); //{a:1}
console.log(z); //{a:1, b:function b(){return '2'}}

从结果看来,Object.assign()可以复制方法,JSON.parse(JSON.stringify())不可以

再来看第第二个坑:

var x = {
  a: 1,
  b: {
    c: 2,
    d: 3,
  },
};

x.c = x.b;
x.d = x.a;
x.b.c = x.c;
x.b.d = x.d;

var y = JSON.parse(JSON.stringify(x));
console.log(x);

/*
Uncaught TypeError: Converting circular structure to JSON

    at JSON.stringify (<anonymous>)
    at <anonymous>:8:25

*/

报错了,其结果表明JSON.parse(JSON.stringify()),不能拷贝循环引用对象

再来看看Object.assign()

var x = {
  a: 1,
  b: {
    c: 2,
    d: 3,
  },
};

x.c = x.b;
x.d = x.a;
x.b.c = x.c;
x.b.d = x.d;

var y = Object.assign({}, x);
console.log(x);
/*
[object Object]{
a:1, 
b:[object, Object], 
d:[object, Object], 
d:1
}
*/

使用展开操作符[... ]

对象字面量的展开操作符目前是ECMAScript

JSON.parse(JSON. stringify ()), und der Erweiterungsoperator [...] von ES6

weil in js The =-Operator kann keine Kopie für ein Objekt erstellen, es handelt sich lediglich um einen Verweis auf das Objekt

Object.assign()

var x = [
  "a",
  "b",
  "c",
  "d",
  {
    e: 1,
  },
];
var y = [...x];
console.log(y); //[&#39;a&#39;, &#39;b&#39;, &#39;c&#39;, &#39;d&#39;, {&#39;e&#39;:1}]

var m = {
  a: 1,
  b: 2,
  c: ["d", "e"],
};
var n = {
  ...m,
};
console.log(n); //{a:1, b:2, c:[&#39;d&#39;, &#39;e&#39;]}

Auf den ersten Blick wird keine Ausnahme gefunden, denn was wir wollen, ist das gewünschte Ergebnis. Machen Sie die Objektstruktur etwas komplizierter und schauen Sie sich dann das an

function copy(x) {
  var y = {};
  for (m in x) {
    y[m] = x[m];
  }
  return y;
}
var o = {
  a: 1,
  b: 2,
  c: {
    d: 3,
    e: 4,
  },
};
var p = copy(o);

Ich habe die Falle entdeckt, als ich anfing, also wurde bewiesen, dass Object.assign() nur eine flache Kopie des Objekts implementiert

Object.assign() Beachten Sie außerdem, dass nicht aufzählbare Objekte mit Attributen in der Prototypenkette nicht kopiert werden können:

var x = {};

Object.defineProperty(x, "m", {
  value: 5,
  writable: false,
});

console.log(x.m); //5
x.m = 25; //这一步没报错,但是也没执行
console.log(x.m); //5

Es ​​ist überraschend, den Wert von z zu erhalten, da x ist die Prototypenkette von y, daher wird x nicht kopiert

Das Attribut b ist ein nicht aufzählbares Attribut Eigenschaft und wird nicht kopiert

Nur c Es kann aufgezählt werden, sodass es auch kopiert werden kann. Die oben genannten Fallstricke können auch sehr gut gelöst werden:

Tief copy JSON.parse (JSON.stringify())

Lösung für die Fallstricke des flachen Kopierens🎜rrreee🎜Natürlich ist diese Kopiermethode im Grunde perfekt für gewöhnliche Objekte, also wo ist ihre Gefahr? 🎜Aus den Ergebnissen: Komm schon, Object.assign() kann die Methode kopieren, JSON.parse(JSON.stringify()) nicht 🎜🎜 Schauen wir uns die zweite Falle an : 🎜rrreee🎜 Es ​​wurde ein Fehler gemeldet und das Ergebnis zeigte, dass JSON.parse(JSON.stringify()), das Zirkelreferenzobjekt nicht kopieren kann🎜🎜Werfen wir einen Blick auf Object. zuweisen()🎜rrreee🎜Verwenden Sie den Spread-Operator [... ]🎜🎜Der Spread-Operator von Objektliteralen ist derzeit ein Phase-3-Vorschlag von ECMAScript Objekte einfacher kopieren🎜rrreee🎜Hinweis Der Spread-Operator ist auch eine flache Kopie. Ist es also wirklich so schwierig, Objekte zu kopieren? 🎜🎜Machen Sie Ihre eigenen Räder: 🎜rrreee🎜Manche Leute sagen, dass es keine großen Probleme geben sollte, wenn Sie dies tun. Dann können wir nur lachen und weitermachen 🎜rrreee🎜 Auf diese Weise stößt der Spread-Operator auch hier auf Fallstricke beim Kopieren von Objekten. 🎜🎜Es gibt überall Fallstricke und es ist schwer, sich vor ihnen zu schützen. 🎜🎜Empfohlenes Lernen: 🎜JavaScript-Video-Tutorial🎜🎜

Das obige ist der detaillierte Inhalt vonEingehende Analyse von Objektkopiermethoden in JavaScript (mit Code). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:chuchur.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen