Maison  >  Article  >  interface Web  >  Analyse approfondie des méthodes de copie d'objets en JavaScript (avec code)

Analyse approfondie des méthodes de copie d'objets en JavaScript (avec code)

奋力向前
奋力向前avant
2021-08-20 09:55:371860parcourir

Dans l'article précédent "Ce que vous devez savoir sur l'utilisation de l'"héritage jquery" JavaScript (explication détaillée du code) ", nous avons appris l'utilisation de l'"héritage jquery" JavaScript. L'article suivant vous présentera la méthode de copie d'objet dans JS. Les amis dans le besoin peuvent s'y référer.

Analyse approfondie des méthodes de copie d'objets en JavaScript (avec code)

En parlant de copie d'objets en javascript, la première chose à laquelle nous pensons est 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 ()), et l'opérateur d'expansion [...] de ES6

car dans js Le L'opérateur = ne peut pas créer une copie pour un objet, c'est juste une référence à l'objet

opérateur

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;]}

Ainsi, lors de l'exécution d'opérations sur un objet, l'opérateur est égal à (=) Non conseillé

Object.assign()

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);

À première vue, aucune exception ne sera trouvée, car ce que nous voulons, c'est le résultat que nous voulons. Rendez la structure de l'objet un peu plus compliquée, puis regardez ceci

.

var x = {};

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

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

J'ai découvert le piège quand j'ai commencé, il a donc été prouvé que Object.assign() n'implémente qu'une copie superficielle de l'objet

Object.assign() Une autre chose à noter est que les objets non énumérables avec des propriétés sur la chaîne prototype ne peuvent pas être copiés. Jetez un œil au code :

rrreee C'est surprenant d'obtenir la valeur de z, car x est la chaîne prototype de <code>y, donc x ne sera pas copié

L'attribut b est un non énumérable propriété et ne sera pas copié🎜🎜Seul c a une description énumérable, il peut donc être copié. Les pièges ci-dessus peuvent également être très bien résolus, et regardez en bas : 🎜🎜Profondément. copy JSON.parse (JSON.stringify())🎜🎜Solution aux pièges de la copie superficielle🎜rrreee🎜Bien sûr, cette méthode de copie est fondamentalement parfaite pour les objets ordinaires, alors où est son piège🎜rrreee 🎜D'après les résultats Allez, Object.assign() peut copier la méthode, JSON.parse(JSON.stringify()) ne peut pas 🎜🎜 Regardons le deuxième piège : 🎜rrreee🎜 Une erreur a été signalée et le résultat a montré que JSON.parse(JSON.stringify()), ne peut pas copier l'objet de référence circulaire🎜🎜Jetons un coup d'œil à Object. assign()🎜rrreee🎜Utiliser l'opérateur Spread [... ]🎜🎜L'opérateur spread des littéraux d'objet est actuellement une proposition de phase 3 de ECMAScript, ce qui rend copier des objets plus simple🎜rrreee🎜Remarque L'opérateur de propagation est également une copie superficielle. Alors, est-ce vraiment si difficile de copier des objets ? 🎜🎜Faites vos propres roues : 🎜rrreee🎜Certaines personnes disent qu'il ne devrait pas y avoir beaucoup de problèmes si vous faites cela. Ensuite, nous ne pouvons que rire et continuer 🎜rrreee🎜 De cette façon, l'opérateur de spread rencontrera également des pièges lors de la copie d'objets ici. 🎜🎜Il y a des pièges partout et il est difficile de s'en prémunir... J'ai écrit ceci et je suppose qu'il y a encore de nombreux pièges qui n'ont pas été entièrement répertoriés🎜🎜J'en écrirai plus plus tard🎜🎜[Fin] 🎜🎜Apprentissage recommandé : 🎜Tutoriel vidéo JavaScript🎜🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer