Иногда в JavaScript возникает задача по клонированию какого-то объекта. И в этот момент не всегда ясно как это правильно нужно делать.
Решение, когда объект имеет один уровень вложенности
Способ № 1 —
У нас есть объект, который мы хотим клонировать. Его глубина равна 1. Вложенных объектов в нём нет.
То есть мы хотим взять все свойства этого объекта и перенести их в новый объект.
let obj22 = {s:123, z:456}
Теперь нам нужно создать новый идентификатор привязки и присвоить ему результат выражения:
литерального объявления объекта и оператора троеточия.

let obj33 = {...obj22}
С этого момента в оперативной памяти живут уже два объекта и две ссылки на них. Клонирование объекта одного уровня вложенности прошло успешно.

Проверка клонирования объекта с одним уровнем вложенности
Давайте изменим их свойства и проверим, что всё правильно склонировалось.
obj22.x = 111
obj33.r = 777

Оригинальный объект хранит свои свойства, а клонированный объект свои. Добавление новых свойств произошло только для каждого из объектов.
Теперь можем изменить свойство, которое клонировали и ещё раз убедиться, что всё ок.
obj22.s = 0

Проблемы, которые возникают при неправильном клонировании
Если пытаться присвоить новому идентификатору привязки, какой-нибудь существующий идентификатор привязки, то мы просто получаем ссылку на один и тот же объект, а не клонируем новый.
Пример проблемы:
let ob1 = {a:"a", b:"b"}; let ob2 = ob1;
В таком виде ob2 будет ссылаться на тот же самый объект что и ob1. Оба идентификатора привязки ссылаются на один и тот же объект.
Это значит, что при изменении свойства от какого-либо идентификатора привязки мы будем менять оригинальный объект.

Если мы у любого идентификатора поменяем значение у свойства A, то изменения отразятся на другом идентификаторе, так как они оба ссылаются на один и тот же объект.
ob1.a = 100

В этом и кроется проблема при неправильном клонировании объектов. В этом случае для одного объекта создаются две ссылки. Изменяя в одном идентификаторе, мы меняем свойства и у другого.
Способ № 2 — Через конструктор Object и его свойство assign
Функция assign используется для копирования значений всех перечисляемых собственных свойств из одного или нескольких исходных объектов в целевой объект.
Пример использования. У нас есть оригинальный объект:
let obj44 = {44:44, 55:55};
В новую переменную obj700 положим результат вызова метода assign()
let obj700 = Object.assign({}, obj44);
Первым параметром у нас будет новый объект, объявленный литерально. Вторым параметром мы передаём тот объект, свойства которого хотим скопировать.
В результате мы получаем новый клон оригинального объекта.

Решение, когда объект имеет несколько уровней вложенности
Пример вложенного объекта:
let o1 = {a:1, b:{f:2, r:3}}
Что будет, если мы попытаемся клонировать этот объект, описанными ранее способами?
// способ через троеточие ... let o2 = {...o1} o2.a = 'R' o1 o2

Мы изменили значение собственного свойства основного объекта. Здесь вроде всё нормально и мы получили желаемый результат.
Но…
Если мы изменим значение у свойства вложенного объекта:
// способ через assign() let o3 = Object.assign({}, o1) o3.b.f = 'S' o1 o3

То нас постигнет неудача. Вложенный объект будет иметь ссылку на вложенный объект предка. Из-за этого, когда мы меняем свойство вложенного объекта клона, то это же свойство меняется и у вложенного объекта предка.
Как решить задачу в ситуации с вложенными объектами?
Если у нас нет никаких методов или функций, а есть только ключи и примитивные значения (внутри основного и вложенных объектов), то можем просто привести такой объект в строке и затем это строку превратить снова в объект.
Делается это при помощи класса JSON и его методов stringify() и parse().
Пример вложенного объекта:
let o1 = {a:1, b:{f:2, r:3}} let o4 = JSON.parse(JSON.stringify(o1)) o4.b.r = 'G' o1 o4
Результат работы:

При таком подходе удаётся создать отдельный независимый объект JavaScript, который также как и его предок хранит примитивы в нужной структуре вложенности.
Функция клонирования объекта, рекурсивная
function clone(object) { let result = {}; for (let key in object) { let value = object[key]; if (value.constructor.name === 'Object' && value !== null) { value = clone(value); } result[key] = value; } return result; }
Информационные ссылки
Стандарт ECMAScript — Раздел «Производство ObjectLiteral» — https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#prod-ObjectLiteral