Важно понимать, что делает =оператор в JavaScript, а что не делает.
=Оператор не делает копию данных.
=Оператор создает новую ссылку на тот же данные.
После запуска исходного кода:
var a = $('#some_hidden_var').val(),
b = a;
aи bтеперь это два разных имени для одного и того же объекта .
Любые изменения, внесенные вами в содержимое этого объекта, будут видны одинаково независимо от того, ссылаетесь ли вы на него через aпеременную или bпеременную. Это один и тот же объект.
Итак, когда вы позже попытаетесь «вернуться» bк исходному aобъекту с помощью этого кода:
b = a;
Код вообще ничего не делает , потому что aи b- это одно и то же. Код такой же, как если бы вы написали:
b = b;
который явно ничего не сделает.
Почему ваш новый код работает?
b = { key1: a.key1, key2: a.key2 };
Здесь вы создаете новый объект с {...}литералом объекта. Этот новый объект не такой, как ваш старый. Итак, теперь вы устанавливаете bссылку на этот новый объект, который делает то, что вы хотите.
Для обработки любого произвольного объекта вы можете использовать функцию клонирования объекта, такую как та, что указана в ответе Арманда, или, поскольку вы используете jQuery, просто используйте эту $.extend()функцию . Эта функция сделает мелкую или глубокую копию объекта. (Не путайте это с $().clone()методом который предназначен для копирования элементов DOM, а не объектов.)
Для мелкой копии:
b = $.extend( {}, a );
Или глубокая копия:
b = $.extend( true, {}, a );
В чем разница между мелкой копией и глубокой копией? Неглубокая копия похожа на ваш код, который создает новый объект с литералом объекта. Он создает новый объект верхнего уровня, содержащий ссылки на те же свойства, что и исходный объект.
Если ваш объект содержит только примитивные типы, такие как числа и строки, глубокая копия и поверхностная копия будут делать то же самое. Но если ваш объект содержит другие объекты или массивы, вложенные в него, то неглубокая копия не копирует эти вложенные объекты, а просто создает ссылки на них. Таким образом, у вас может быть та же проблема с вложенными объектами, что и с вашим объектом верхнего уровня. Например, с учетом этого объекта:
var obj = {
w: 123,
x: {
y: 456,
z: 789
}
};
Если вы сделаете неглубокую копию этого объекта, тогда xсвойством вашего нового объекта будет тот же xобъект, что и у оригинала:
var copy = $.extend( {}, obj );
copy.w = 321;
copy.x.y = 654;
Теперь ваши объекты будут выглядеть так:
// 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
}
};
Вы можете избежать этого с помощью глубокой копии. Глубокая копия повторяется во всех вложенных объектах и массивах (и в Date в коде Арманда), чтобы сделать копии этих объектов так же, как и копию объекта верхнего уровня. Так что изменение copy.x.yне повлияетobj.x.y .
Краткий ответ: если сомневаетесь, возможно, вам понадобится глубокая копия.
aбыло установлено,.val()я предполагаю, что это JSON (строка), а не объект - верно? Используете ли выJSON.parse(a)в какой-то момент, чтобы получить реальный объект?