TLDR;
// Use this approach
//Method 1 - clone will inherit the prototype methods of the original.
let cloneWithPrototype = Object.assign(Object.create(Object.getPrototypeOf(original)), original);
В Javascript не рекомендуется делать расширения прототипа, это приведет к проблемам, когда вы будете тестировать свой код/компоненты. Фреймворки модульного тестирования не будут автоматически принимать расширения вашего прототипа. Так что это не очень хорошая практика. Здесь есть больше объяснений расширений прототипа ?
Для клонирования объектов в JavaScript нет простого или прямого способа. Вот первый пример использования Shallow Copy:
1 -> Мелкий клон:
class Employee {
constructor(first, last, street) {
this.firstName = first;
this.lastName = last;
this.address = { street: street };
}
logFullName() {
console.log(this.firstName + ' ' + this.lastName);
}
}
let original = new Employee('Cassio', 'Seffrin', 'Street A, 23');
//Method 1 - clone will inherit the prototype methods of the original.
let cloneWithPrototype = Object.assign(Object.create(Object.getPrototypeOf(original)), original);
//Method 2 - object.assing() will not clone the Prototype.
let cloneWithoutPrototype = Object.assign({},original);
//Method 3 - the same of object assign but shorter syntax using "spread operator"
let clone3 = { ...original };
//tests
cloneWithoutPrototype.firstName = 'John';
cloneWithoutPrototype.address.street = 'Street B, 99'; //will not be cloned
Результаты:
оригинал.logFullName();
результат: Кассио Сеффрин
cloneWithPrototype.logFullName();
результат: Кассио Сеффрин
исходный.адрес.улица;
результат: 'Улица B, 99' // обратите внимание, что исходный подобъект был изменен
Примечание. Если у экземпляра есть замыкания как собственные свойства, этот метод не будет его обертывать. (узнайте больше о замыканиях). Кроме того, адрес подобъекта будет не получить клон.
cloneWithoutPrototype.logFullName()
Не будет работать. Клон не наследует ни один из методов прототипа оригинала.
cloneWithPrototype.logFullName()
будет работать, потому что клон также будет копировать свои прототипы.
Чтобы клонировать массивы с помощью Object.assign:
let cloneArr = array.map((a) => Object.assign({}, a));
Клонировать массив, используя синтаксис распространения ECMAScript:
let cloneArrSpread = array.map((a) => ({ ...a }));
2 -> Глубокий клон:
Чтобы заархивировать совершенно новую ссылку на объект, мы можем использовать JSON.stringify() для анализа исходного объекта как строки и после его анализа обратно в JSON.parse().
let deepClone = JSON.parse(JSON.stringify(original));
При глубоком клонировании ссылки на адрес будут сохранены. Однако прототипы deepClone будут потеряны, поэтому deepClone.logFullName() не будет работать.
3 -> сторонние библиотеки:
Другими вариантами будут использование сторонних библиотек, таких как loadash или underscore. Они создают новый объект и копируют каждое значение из оригинала в новый объект, сохраняя его ссылки в памяти.
Подчеркивание: пусть cloneUnderscore = _(original).clone();
Клон Loadash: var cloneLodash = _.cloneDeep(original);
Недостатком lodash или подчеркивания была необходимость включать в проект дополнительные библиотеки. Однако они являются хорошими вариантами и также дают высокие результаты производительности.
person
Cassio Seffrin
schedule
27.12.2019
Object
, используемых в качестве держателей данных. Это касается ES6class
es и проблемы с тем, чтобы не потерять информацию о типе класса. Нужно другое решение. - person flori   schedule 28.10.2017