У меня есть переменная, значение которой имеет объект JSON. Я напрямую назначаю эту переменную какой-то другой переменной, чтобы они имели одинаковое значение. Вот как это работает:
var a = $('#some_hidden_var').val(),
b = a;
Это работает, и оба имеют одинаковую ценность. Я использую mousemove
обработчик событий для обновления b
всего приложения. При нажатии кнопки я хочу вернуться b
к исходному значению, то есть к значению, хранящемуся в a
.
$('#revert').on('click', function(e){
b = a;
});
После этого, если я использую тот же mousemove
обработчик событий, он обновляет оба, a
а b
когда раньше он обновлял толькоb
как ожидалось.
Я в тупике по этому поводу! Что здесь не так?
javascript
jquery
Рутвик Гангурд
источник
источник
a
было установлено,.val()
я предполагаю, что это JSON (строка), а не объект - верно? Используете ли выJSON.parse(a)
в какой-то момент, чтобы получить реальный объект?$.parseJSON
для преобразования в объект. Структура:{ 'key': {...}, 'key': {...}, ...}
. Извините, я не могу разместить здесь код, это запрещено на моем рабочем месте!a
это объект?a
это глобальная переменная?$.parseJSON()
взялось?), Трудно сказать, в чем проблема. Что касается правил вашего рабочего места, вам не нужно публиковать свой реальный реальный код полностью, просто приведите более короткий и общий пример, демонстрирующий проблему (и, в идеале, включите ссылку на живую демонстрацию на jsfiddle.net ) .Ответы:
Важно понимать, что делает
=
оператор в JavaScript, а что не делает.=
Оператор не делает копию данных.=
Оператор создает новую ссылку на тот же данные.После запуска исходного кода:
a
иb
теперь это два разных имени для одного и того же объекта .Любые изменения, внесенные вами в содержимое этого объекта, будут видны одинаково независимо от того, ссылаетесь ли вы на него через
a
переменную илиb
переменную. Это один и тот же объект.Итак, когда вы позже попытаетесь «вернуться»
b
к исходномуa
объекту с помощью этого кода:Код вообще ничего не делает , потому что
a
иb
- это одно и то же. Код такой же, как если бы вы написали:который явно ничего не сделает.
Почему ваш новый код работает?
Здесь вы создаете новый объект с
{...}
литералом объекта. Этот новый объект не такой, как ваш старый. Итак, теперь вы устанавливаетеb
ссылку на этот новый объект, который делает то, что вы хотите.Для обработки любого произвольного объекта вы можете использовать функцию клонирования объекта, такую как та, что указана в ответе Арманда, или, поскольку вы используете jQuery, просто используйте эту
$.extend()
функцию . Эта функция сделает мелкую или глубокую копию объекта. (Не путайте это с$().clone()
методом который предназначен для копирования элементов DOM, а не объектов.)Для мелкой копии:
Или глубокая копия:
В чем разница между мелкой копией и глубокой копией? Неглубокая копия похожа на ваш код, который создает новый объект с литералом объекта. Он создает новый объект верхнего уровня, содержащий ссылки на те же свойства, что и исходный объект.
Если ваш объект содержит только примитивные типы, такие как числа и строки, глубокая копия и поверхностная копия будут делать то же самое. Но если ваш объект содержит другие объекты или массивы, вложенные в него, то неглубокая копия не копирует эти вложенные объекты, а просто создает ссылки на них. Таким образом, у вас может быть та же проблема с вложенными объектами, что и с вашим объектом верхнего уровня. Например, с учетом этого объекта:
Если вы сделаете неглубокую копию этого объекта, тогда
x
свойством вашего нового объекта будет тот жеx
объект, что и у оригинала:Теперь ваши объекты будут выглядеть так:
Вы можете избежать этого с помощью глубокой копии. Глубокая копия повторяется во всех вложенных объектах и массивах (и в Date в коде Арманда), чтобы сделать копии этих объектов так же, как и копию объекта верхнего уровня. Так что изменение
copy.x.y
не повлияетobj.x.y
.Краткий ответ: если сомневаетесь, возможно, вам понадобится глубокая копия.
источник
$.extend()
функцию. Подробности выше. :-)Я обнаружил, что использование JSON работает, но следите за циклическими ссылками
источник
let a = {}; let b = {a:a}; a.b = b; JSON.stringify(a)
выдаствопрос уже решен довольно давно, но для дальнейшего использования возможное решение
Будьте осторожны, это работает правильно, только если a - невложенный массив чисел и строк.
источник
newVariable = originalVariable.valueOf();
для предметов, которые вы можете использовать,
b = Object.assign({},a);
источник
Причина этого проста. JavaScript использует ссылки, поэтому, когда вы назначаете,
b = a
вы назначаете ссылку,b
таким образом, при обновленииa
вы также обновляетеb
Я нашел это в stackoverflow и помогу предотвратить подобные вещи в будущем, просто вызвав этот метод, если вы хотите сделать глубокую копию объекта.
источник
if (obj instanceof x) { ... }
должно быть иначе, если?Я не понимаю, почему ответы такие сложные. В Javascript примитивы (строки, числа и т. Д.) Передаются по значению и копируются. Объекты, включая массивы, передаются по ссылке. В любом случае присвоение «a» нового значения или ссылки на объект не изменит «b». Но изменение содержимого 'a' изменит содержимое 'b'.
Вставьте любую из вышеперечисленных строк (по одной) в узел или любую консоль javascript браузера. Затем введите любую переменную, и консоль покажет ее значение.
источник
Для строк или входных значений вы можете просто использовать это:
источник
Большинство ответов здесь используют встроенные методы или библиотеки / фреймворки. Этот простой метод должен работать нормально:
источник
Object.assign({},a)
Решил пока сам. Исходное значение имеет только 2 подсвойства. Я преобразовал новый объект со свойствами из,
a
а затем назначил егоb
. Теперь мой обработчик событий обновляетсяb
, а исходныйa
остается как есть.Это прекрасно работает. Я не изменил ни одной строчки в своем коде, за исключением приведенного выше, и он работает именно так, как я хотел. Так что поверьте мне, больше ничего не обновлялось
a
.источник
Решение для AngularJS :
источник