В JavaScript поверхностная копия — это копия объекта, которая копирует только ссылку на объект, а не создает новый объект с отдельной копией данных объекта. С другой стороны, глубокая копия — это копия объекта, которая создает новый объект с отдельной копией данных объекта, включая любые вложенные объекты или массивы.
Вот пример неглубокой копии в JavaScript:
const original = { a: 1, b: { c: 2 } }; const copy = original; console.log(copy); // { a: 1, b: { c: 2 } } copy.a = 2; console.log(original.a); // 2 (the original object is modified)
В JavaScript вы можете создать глубокую копию объекта, используя методы JSON.parse()
и JSON.stringify()
. Вот пример того, как вы можете использовать эти методы для создания глубокой копии объекта:
function deepCopy(obj) { return JSON.parse(JSON.stringify(obj)); } const original = { a: 1, b: { c: 2 } }; const copy = deepCopy(original); console.log(copy); // { a: 1, b: { c: 2 } }
Метод JSON.stringify()
преобразует объект в строку JSON, а метод JSON.parse()
анализирует строку JSON и создает из нее новый объект. Этот метод — быстрый и простой способ создать глубокую копию объекта, но он имеет некоторые ограничения. Он работает только с простыми объектами и массивами и не работает с объектами, имеющими функции или циклические ссылки.
Если вам нужно создать глубокую копию более сложного объекта, вы можете использовать рекурсивную функцию для перебора свойств объекта и создания нового объекта с той же структурой. Вот пример того, как вы можете это сделать:
function deepCopy(obj) { if (obj === null || typeof obj !== 'object') { return obj; } let copy; if (Array.isArray(obj)) { copy = []; } else { copy = {}; } for (const key in obj) { copy[key] = deepCopy(obj[key]); } return copy; } const original = { a: 1, b: { c: 2 } }; const originalArray = [1,2,3,4,5,6,7]; const copyArray = deepCopy(originalArray); const copy = deepCopy(original); console.log(copy); // { a: 1, b: { c: 2 } } console.log(copyArray); // [1,2,3,4,5,6,7]
Эта функция использует рекурсивный подход для создания нового объекта с той же структурой, что и исходный объект. Он проверяет тип входного объекта и, если это массив или объект, создает новый массив или объект и рекурсивно копирует свойства входного объекта в новый объект. Если входной объект является примитивным значением (например, числом или строкой), он просто возвращает значение. Этот подход работает для более сложных объектов и правильно обрабатывает циклические ссылки.
Циклическая ссылка в JavaScript возникает, когда у объекта есть свойство, которое ссылается на сам объект или на объект, содержащий ссылку на исходный объект. Вот несколько примеров циклических ссылок в JavaScript:
- Объект, у которого есть свойство, ссылающееся на сам объект:
const obj = {}; obj.self = obj;
2. Объект, у которого есть свойство, ссылающееся на другой объект, содержащий ссылку на исходный объект:
const obj1 = {}; const obj2 = { parent: obj1 }; obj1.child = obj2;
3. Объект, у которого есть свойство, ссылающееся на массив, содержащий ссылку на объект:
const obj = {}; obj.array = [obj];
Циклические ссылки могут вызвать проблемы при попытке сериализовать объект с помощью JSON.stringify()
, потому что процесс сериализации застрянет в бесконечном цикле, пытаясь сериализовать циклические ссылки. Чтобы избежать этой проблемы, вы можете использовать пользовательскую функцию замены с JSON.stringify()
для фильтрации циклических ссылок при сериализации объекта.
function replacer(key, value) { if (value === this) { return undefined; } return value; } const obj = {}; obj.self = obj; console.log(JSON.stringify(obj, replacer)); // {}