web-dev-qa-db-fra.com

Quelle est la différence entre le soulignement clone () et le simple '='?

Il s'agit des meilleures pratiques lorsque vous devez copier un objet en javascript.

Par exemple:

J'ai un objet { name: 'Dodo', method: function () { console.log(this.name) }};

J'ai besoin d'en créer une copie:

var obj = { name: 'Dodo', method: function () { console.log(this.name) } };
// what is better?
var copyUnderscore = _(obj).clone();
var copySimple = obj;

Quelle est la meilleure façon? Merci!

23
Kosmetika

_.clone Est complètement différent de l'affectation.

_.clone Crée un nouvel objet et copie chaque valeur de l'original vers le nouvel objet.

Une affectation pointe simplement une variable sur l'objet qui existe déjà.

Supposons que vous aviez un chiot. Appelons-le Rex.

Si vous discutez de Rex avec quelqu'un, vous l'appellerez Rex, ou peut-être "le chien". Ces deux éléments font référence à l'animal en question. Une affectation est analogue à l'utilisation de différentes phrases pour votre animal de compagnie:

rex = {
  type: 'Dog',
  age: '12 Weeks',
  name: "Rex",
  fixed: false,
  fix: function() {
    this.fixed = true;
    console.log(this.name + " Fixed.");
  }
};
theDog = rex;

// Note the use of `===`, which checks for object identity.
// Assignment (as above) is the whole point of `===`
if (theDog === rex) {
   alert("The Dog is the Same as Rex");
}

Lorsque vous changez quelque chose sur l'un, il change pour les deux références. Supposons donc que vous "répariez" Rex:

rex = {
  type: 'Dog',
  age: '12 Weeks',
  name: "Rex",
  fixed: false,
  fix: function() {
    this.fixed = true;
    console.log(this.name + " Fixed.");
  }
};
theDog = rex;
rex.fix();

alert("The Dog is " + (theDog.fixed ? "" : "not ") + "fixed");
alert("Rex is " + (rex.fixed ? "" : "not ") + "fixed");

theDog est également corrigé.

Supposons maintenant que vous ayez cloné Rex. (Imaginons qu'il ne soit pas encore résolu pour des raisons d'argument).

rex = {
  type: 'Dog',
  age: '12 Weeks',
  name: "Rex",
  fixed: false,
  fix: function() {
    this.fixed = true;
    console.log(this.name + " Fixed.");
  }
};
theDog = rex;
otherDog = _.clone(rex);

console.log(theDog);
console.log(rex);
console.log(otherDog);

var message = rex === theDog ? "Rex is the same as the dog" : "Rex and the dog are different";
message += "\n";
message += rex === otherDog ? "Rex is the same as the other dog" : "Rex is different from the other dog";
message += "\n";
message += rex.fixed ? "Rex is fixed" : "Rex is not fixed";
message += "\n";
message += otherDog.fixed ? "Other dog is fixed" : "Other dog is not fixed";

alert(message);

otherDog.fix();

message = rex.fixed ? "Rex is fixed" : "Rex is not fixed";
message += "\n";
message += otherDog.fixed ? "Other dog is fixed" : "Other dog is not fixed";
alert(message);
<script src="http://underscorejs.org/underscore-min.js"></script>

Chaque valeur de rex a été copiée dans otherDog. Miraculeusement, "otherDog" est né à l'âge de 12 semaines. Mais la fixation de l'un va pas réparer l'autre.

Maintenant que rex et theDog sont le même chien, aucun n'est corrigé. Cependant, otherDog est fixe. C'est un clone, pas le même animal.

Il y a quelques subtilités à se méfier. _.clone Ne copie pas en profondeur. Cela signifie que tout objet ou tableau qui est une valeur dans l'objet cloné est copié par affectation vers le nouvel objet (voir le premier extrait pour un examen de ce que cela signifie).

Cela signifie que si rex avait une propriété mother qui était un objet représentant sa mère, elle serait partagée entre rex et otherDog. Toute modification de la mère de rex serait propagée à otherDog. Ce n'est pas si différent de la vraie vie; la mère biologique est une seule et même personne.

[~ # ~] modifier [~ # ~]

Autre remarque miraculeuse: le clonage d'un chien fixe produit un autre chien fixe. C'est là que la métaphore biologique se décompose.

MODIFIER ENCORE (juin 2018)

Il existe deux fonctionnalités ES6 supplémentaires qui pourraient intéresser les lecteurs de cette question:

Splat d'objet

Ce qui suit est identique à _.clone (Copie les membres):

let x = {...rex};

Object.assign

Ce qui suit copie les membres dans un objet existant, puis renvoie cet objet:

let x = {}; let anotherReferenceToX = Object.assign(x, rex);

BONUS!

Il convient de noter que lodash en fait a une opération de clonage en profondeur . Vous pouvez également utiliser function (x) { return JSON.parse(JSON.stringify(x)) }. Mais cela va étouffer les références circulaires, et pas le lodash.

83
Crisfole