Ответ
Для создания копий объектов используется шаблон Прототип (Prototype), который можно выразить через интерфейс с методом clone().
Пример интерфейса Cloneable и его реализации:
// Обобщенный (generic) интерфейс для клонирования
interface Cloneable<T> {
clone(): T;
}
// Класс, реализующий интерфейс. Важно создать глубокую (deep) копию.
class UserSettings implements Cloneable<UserSettings> {
constructor(
public theme: string,
public notificationsEnabled: boolean,
public preferences: string[] // Массив - ссылочный тип!
) {}
// Метод clone() создает новый независимый объект
clone(): UserSettings {
// Глубокая копия для корректного клонирования ссылочных типов
return new UserSettings(
this.theme, // Примитив - копируется по значению
this.notificationsEnabled, // Примитив
[...this.preferences] // Создаем КОПИЮ массива
);
}
}
// Пример использования
const originalSettings = new UserSettings('dark', true, ['email', 'sms']);
const clonedSettings = originalSettings.clone();
// Меняем клон
clonedSettings.theme = 'light';
clonedSettings.preferences.push('push');
console.log(originalSettings.theme); // 'dark' (оригинал не изменился)
console.log(originalSettings.preferences); // ['email', 'sms'] (оригинальный массив не изменился!)
console.log(clonedSettings.preferences); // ['email', 'sms', 'push']
Ключевые моменты:
- Интерфейс
Cloneable<T>задает контракт для любых клонируемых объектов. - Глубокая копия (Deep Copy): Критически важно корректно копировать вложенные объекты и массивы (используем spread оператор
[...]илиArray.from()). Поверхностное копирование приведет к тому, что клон и оригинал будут разделять ссылки на одни и те же вложенные объекты. - Применение: Полезно для создания снимков (snapshots) состояния, отката изменений или работы с объектами, которые не должны меняться после передачи в другие части системы.