Как скопировать объект JavaScript в новую переменную НЕ по ссылке?

Я быстро написал здесь jsfiddle, в котором я передаю небольшой объект JSON в новую переменную и изменяю данные из исходной переменной (не из новой переменной), но данные новой переменной также обновляются. Это должно означать, что объект JSON был передан по ссылке, верно?

Вот мой быстрый код:

var json_original = {one:'one', two:'two'}

var json_new = json_original;

console.log(json_original); //one, two
console.log(json_new); //one, two

json_original.one = 'two';
json_original.two = 'one';

console.log(json_original); //two, one
console.log(json_new); //two, one

Есть ли способ сделать глубокую копию объекта JSON, чтобы изменение исходной переменной не повлияло на новую переменную?


person Prusprus    schedule 21.08.2013    source источник
comment
Там нет JSON. Пожалуйста, не путайте объекты JavaScript с JSON.   -  person Quentin    schedule 21.08.2013
comment
@Quentin, спасибо, я прочитаю разницу между объектами javacript и json (ref: stackoverflow.com/questions/6489783/)   -  person Prusprus    schedule 21.08.2013
comment
Не думайте, что это дубликат, ответ не был найден в другой ветке.   -  person Prusprus    schedule 21.08.2013
comment
@Quentin, значит, если бы мы говорили исключительно в рамках javascript, JSON и объект Javascript были бы эквивалентны? JSON отличается тем, что его можно адаптировать к языку, на котором он интерпретируется?   -  person Prusprus    schedule 21.08.2013
comment
В рамках JavaScript JSON является либо форматом данных, либо объектом, содержащим методы для преобразования объектов JavaScript в строковые представления этого формата данных и обратно.   -  person Quentin    schedule 21.08.2013
comment
Это не дубликат, Prusprus попросил ответ с помощью javascript, а не js jquery библиотеки ... нет ли простого способа с ES6-ES7 полностью клонировать объект js в новом пространстве в памяти?   -  person Bizarre    schedule 02.04.2018
comment
Взгляните на ES6 Object.assign ()   -  person Aditya Prasoon    schedule 01.06.2020
comment
Я также считаю, что _.clone и _.deepClone lodash достаточно просты в использовании.   -  person Aditya Prasoon    schedule 01.06.2020
comment
@Bizarre не смог опубликовать новый ответ, но учитывая var first = {key: "value"}, затем клонировать его в ES6: var myObj = {...first} и в ES5: var myES5Obj = eval(first.toSource())   -  person bluejayke    schedule 03.06.2020
comment
@AdityaPrasoon чем отличается от var nnewObj = {...old}?   -  person bluejayke    schedule 03.06.2020
comment
@bluejayke Почти то же самое, но не совсем. Проверьте это - 2ality.com / 2016/10 /   -  person Aditya Prasoon    schedule 03.06.2020
comment
Кто-нибудь знает, почему это больно, мне кажется, что возможность сделать копию чего-то очень полезна, почему это не так просто, как '= / =' или что-то в этом роде?   -  person Colin Smith    schedule 29.07.2020


Ответы (2)


Я обнаружил, что следующее работает, если вы не используете jQuery и заинтересованы только в клонировании простых объектов (см. Комментарии).

JSON.parse(JSON.stringify(json_original));

Документация

person Community    schedule 21.08.2013
comment
Не работает для функций, только для свойств (переменных) внутри объекта. - person Harold; 27.04.2014
comment
Это творило для меня чудеса после того, как у меня возникли проблемы с jQuery.extend отличной техникой. - person Kiee; 18.07.2014
comment
При этом даты будут преобразованы в строку и останутся строками даже после анализа. - person Onur Yıldırım; 08.12.2014
comment
Обратите внимание, что это не будет работать для объектов с циклическими ссылками. - person DarkChipolata; 30.01.2015
comment
Это именно то, что я искал, а не Object.create. Немного дорогой способ сериализации и десериализации, но работает для простых объектов со свойствами. - person animageofmine; 23.12.2015
comment
В качестве ванильного решения он все еще кажется таким «хакерским», было бы неплохо, если бы был более «правильный» способ достижения этого. - person jarodsmk; 10.03.2017
comment
НЕ будет работать, если ваш объект содержит функции, используйте let _newObject = Object.assing({}, _oldObject);, чтобы получить относительно хорошую стратегию клонирования. Хотя я бы посоветовал использовать подчеркивание, lodash или другую библиотеку глубокого клонирования. - person Agnibha; 19.04.2017
comment
Вот почему в моем ответе говорится о простых объектах, но я думаю, что это могло бы быть яснее. - person Andy; 19.05.2017
comment
JSON.parse (JSON.stringify (object)) приведет к тому, что все даты будут преобразованы в строки. - person Wilson; 04.08.2017
comment
Это сработало отлично, в моем случае клонирование состояния Vue Vuex, которое потребовало небольшой модификации для удаления конфиденциальных данных, сохраняющихся в локальном хранилище. - person Leo; 01.02.2018
comment
не могли бы вы объяснить, что он делает? или сделать ссылку на JSON.parse и строковить? - person René Datenschutz; 07.06.2019
comment
@animageofmine, почему не var newObj = eval(oldObj.toSource()) для es5 и var newObj = {...oldObj} для es6? - person bluejayke; 03.06.2020
comment
Святые ведра, это просто спасло мое рассудок! - person paulmiller3000; 19.12.2020

Единственный вариант - как-то клонировать объект.

См. этот вопрос о stackoverflow о том, как этого добиться.

Для простых объектов JSON самый простой способ:

var newObject = JSON.parse(JSON.stringify(oldObject));

если вы используете jQuery, вы можете использовать:

// Shallow copy
var newObject = jQuery.extend({}, oldObject);

// Deep copy
var newObject = jQuery.extend(true, {}, oldObject);

ОБНОВЛЕНИЕ 2017: Я должен упомянуть, поскольку это популярный ответ, что теперь есть лучшие способы добиться этого, используя более новые версии javascript:

В ES6 или TypeScript (2.1+):

var shallowCopy = { ...oldObject };

var shallowCopyWithExtraProp = { ...oldObject, extraProp: "abc" };

Обратите внимание, что если extraProp также является свойством для oldObject, его значение не будет использоваться, потому что extraProp : "abc" указывается позже в выражении, которое, по сути, переопределяет его. Конечно, oldObject не будет изменен.

person Moeri    schedule 21.08.2013
comment
Я предпочитаю этот ответ из-за раздела In ES6 или TypeScript (2.1+) :. Также хорош пример глубокой / поверхностной копии JQuery. - person Jacob Barnes; 03.03.2020
comment
Я думаю, это должен быть ответ. - person Mohammad Taherian; 19.06.2020