Найти в Дзене
Программист - турист

Глубокое клонирование объектов js. Почему не стоит использовать JSON.parse

Наверняка, многие из вас сталкивались с проблемой клонирования объектов. И скорей всего сталкивались с проблемой, когда спред ({ ...foo }) не работал на вложенные объекты (массивы). Хотя в интернете написано, что работает. Для тех, кто не знает расскажу.
Есть два типа клонирования - поверхностное и глубокое.
Поверхностное, если простым языком, замена ссылки вашей переменной на новую. Например: const foo = { a: 1, b: 2, c: { x: 2 } };
const oldFoo = foo;
const newFoo = { ...foo };
oldFoo.a = 2;
newFoo.a = 3; После данных операций мы получим на выходе такие объекты: foo - { a: 2, b: 2, c: { x: 2 } };
oldFoo - идентичен foo
newFoo - { a: 3, b: 2, c: { x: 2 } }; Но если мы изменим newFoo.c, то это отразится на foo и oldFoo т.к. объект скопирован только по верхам. Для этого нам необходимо глубокое клонирование, самый простой вариант: JSON.parse(JSON.stringify(foo));
Но не всё так гладко. Давайте представим, что foo не Object, а undefined или function.
Можете проверить, ничем хорошим это не

Наверняка, многие из вас сталкивались с проблемой клонирования объектов. И скорей всего сталкивались с проблемой, когда спред ({ ...foo }) не работал на вложенные объекты (массивы). Хотя в интернете написано, что работает.

Для тех, кто не знает расскажу.
Есть два типа клонирования - поверхностное и глубокое.
Поверхностное, если простым языком, замена ссылки вашей переменной на новую. Например:

const foo = { a: 1, b: 2, c: { x: 2 } };
const oldFoo = foo;
const newFoo = { ...foo };
oldFoo.a = 2;
newFoo.a = 3;

После данных операций мы получим на выходе такие объекты:

foo - { a: 2, b: 2, c: { x: 2 } };
oldFoo - идентичен foo
newFoo - { a: 3, b: 2, c: { x: 2 } };

Но если мы изменим newFoo.c, то это отразится на foo и oldFoo т.к. объект скопирован только по верхам.

Для этого нам необходимо глубокое клонирование, самый простой вариант: JSON.parse(JSON.stringify(foo));
Но не всё так гладко.

Давайте представим, что foo не Object, а undefined или function.
Можете проверить, ничем хорошим это не закончится)

Значит нам надо попробовать другое решение. Например написать функцию, где будет проверяться наличие того, что нам не нужно.

Но лучше взять lodash clonedeep или написать (взять в интернете) рекурсивную функцию.