Il est important de comprendre ce que =
fait et ne fait pas l' opérateur JavaScript.
L' =
opérateur ne fait pas de copie des données.
L' =
opérateur crée une nouvelle référence aux mêmes données.
Après avoir exécuté votre code d'origine:
var a = $('#some_hidden_var').val(),
b = a;
a
et b
sont maintenant deux noms différents pour le même objet .
Toute modification que vous apportez au contenu de cet objet sera vue de la même manière que vous le référeniez via la a
variable ou la b
variable. Ce sont le même objet.
Ainsi, lorsque vous essayez plus tard de "revenir" b
à l' a
objet d' origine avec ce code:
b = a;
Le code ne fait rien du tout , car a
et b
sont exactement la même chose. Le code est le même que si vous aviez écrit:
b = b;
qui évidemment ne fera rien.
Pourquoi votre nouveau code fonctionne-t-il?
b = { key1: a.key1, key2: a.key2 };
Ici, vous créez un tout nouvel objet avec le {...}
littéral objet. Ce nouvel objet n'est pas le même que votre ancien objet. Vous définissez donc maintenant b
comme référence ce nouvel objet, qui fait ce que vous voulez.
Pour gérer n'importe quel objet arbitraire, vous pouvez utiliser une fonction de clonage d'objet telle que celle répertoriée dans la réponse d'Armand, ou puisque vous utilisez jQuery, utilisez simplement la $.extend()
fonction . Cette fonction fera une copie superficielle ou une copie profonde d'un objet. (Ne confondez pas cela avec la $().clone()
méthode qui consiste à copier des éléments DOM, pas des objets.)
Pour une copie superficielle:
b = $.extend( {}, a );
Ou une copie complète:
b = $.extend( true, {}, a );
Quelle est la différence entre une copie superficielle et une copie profonde? Une copie superficielle est similaire à votre code qui crée un nouvel objet avec un littéral d'objet. Il crée un nouvel objet de niveau supérieur contenant des références aux mêmes propriétés que l'objet d'origine.
Si votre objet ne contient que des types primitifs tels que des nombres et des chaînes, une copie profonde et une copie superficielle feront exactement la même chose. Mais si votre objet contient d'autres objets ou tableaux imbriqués à l'intérieur, alors une copie superficielle ne copie pas ces objets imbriqués, elle crée simplement des références à eux. Vous pourriez donc avoir le même problème avec les objets imbriqués que vous aviez avec votre objet de niveau supérieur. Par exemple, étant donné cet objet:
var obj = {
w: 123,
x: {
y: 456,
z: 789
}
};
Si vous faites une copie superficielle de cet objet, alors la x
propriété de votre nouvel objet est le même x
objet que l'original:
var copy = $.extend( {}, obj );
copy.w = 321;
copy.x.y = 654;
Maintenant, vos objets ressembleront à ceci:
// copy looks as expected
var copy = {
w: 321,
x: {
y: 654,
z: 789
}
};
// But changing copy.x.y also changed obj.x.y!
var obj = {
w: 123, // changing copy.w didn't affect obj.w
x: {
y: 654, // changing copy.x.y also changed obj.x.y
z: 789
}
};
Vous pouvez éviter cela avec une copie complète. La copie profonde est récursée dans chaque objet et tableau imbriqués (et Date dans le code d'Armand) pour faire des copies de ces objets de la même manière qu'elle a fait une copie de l'objet de niveau supérieur. Donc changer copy.x.y
n'affecterait pas obj.x.y
.
Réponse courte: en cas de doute, vous voulez probablement une copie complète.
a
été défini à partir de,.val()
je suppose que c'est JSON (une chaîne), pas un objet - est-ce vrai? Utilisez-vousJSON.parse(a)
à un moment donné pour obtenir un objet réel?