← Назад к вопросам

Как работает Structed Clone?

2.0 Middle🔥 121 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как работает Structured Clone

Structured Clone — это встроенный API браузера для глубокого копирования объектов. Это мощнее и удобнее чем JSON.stringify/parse, так как поддерживает больше типов данных.

1. Основы Structured Clone

Api позволяет скопировать объект полностью со всеми вложенными свойствами:

// Мелкое копирование (shallow copy) - НЕПРАВИЛЬНО
const original = { name: 'Иван', address: { city: 'Москва' } };
const shallow = { ...original }; // spread оператор

shallow.address.city = 'СПб';
console.log(original.address.city); // СПб - изменилась оригинал!

// Глубокое копирование (deep copy) - ПРАВИЛЬНО
const deep = structuredClone(original);
deep.address.city = 'СПб';
console.log(original.address.city); // Москва - оригинал не изменилась

2. Синтаксис

// Базовый синтаксис
const original = { /* объект */ };
const clone = structuredClone(original);

// С опциями (для более сложных случаев)
const clone = structuredClone(original, { transfer: [ /* опции */ ] });

3. Поддерживаемые типы

Structured Clone поддерживает намного больше типов чем JSON:

// Примитивные типы
const primitives = {
  string: 'hello',
  number: 123,
  boolean: true,
  null: null,
  undefined: undefined
};
const cloned1 = structuredClone(primitives); // ✅ Работает

// Встроенные объекты
const objects = {
  date: new Date('2024-01-01'),
  regex: /hello/gi,
  map: new Map([['key', 'value']]),
  set: new Set([1, 2, 3]),
  arrayBuffer: new ArrayBuffer(10),
  uint8Array: new Uint8Array([1, 2, 3])
};
const cloned2 = structuredClone(objects); // ✅ Работает всё!

// JSON.stringify не может это (вернёт {})
const json = JSON.stringify(objects);
console.log(json); // Потеря информации!

4. Сравнение с другими методами

const original = { 
  name: 'Test',
  date: new Date(),
  nested: { value: 42 }
};

// ПЛОХО: Object.assign (мелкое копирование)
const copy1 = Object.assign({}, original);
copy1.nested.value = 100;
console.log(original.nested.value); // 100 - изменилась!

// ПЛОХО: spread оператор (мелкое копирование)
const copy2 = { ...original };
copy2.nested.value = 100;
console.log(original.nested.value); // 100 - изменилась!

// ПЛОХО: JSON.stringify (теряет типы данных)
const copy3 = JSON.parse(JSON.stringify(original));
console.log(copy3.date instanceof Date); // false - стала строкой!

// ХОРОШО: structuredClone (полное копирование)
const copy4 = structuredClone(original);
copy4.nested.value = 100;
console.log(original.nested.value); // 42 - оригинал не изменилась!
console.log(copy4.date instanceof Date); // true - тип сохранился!

5. Практические примеры

Работа с Redux/State Management

// Вместо иммутабельного обновления state
const reducer = (state, action) => {
  // ПЛОХО: мутирует оригинал
  state.user.name = 'Новое имя';
  return state;
  
  // ХОРОШО: создаёт новую копию
  const newState = structuredClone(state);
  newState.user.name = 'Новое имя';
  return newState;
};

Копирование сложных объектов

const userData = {
  id: 1,
  name: 'Иван',
  createdAt: new Date(),
  profile: {
    bio: 'Frontend Developer',
    skills: ['JavaScript', 'React', 'TypeScript'],
    social: new Map([
      ['twitter', '@ivan'],
      ['github', 'ivan-dev']
    ])
  }
};

// Глубокое копирование со всеми типами
const backup = structuredClone(userData);
backup.profile.skills.push('Vue.js');

console.log(userData.profile.skills); // ['JavaScript', 'React', 'TypeScript']
console.log(backup.profile.skills);   // ['JavaScript', 'React', 'TypeScript', 'Vue.js']

Работа с бинарными данными

const binaryData = {
  buffer: new ArrayBuffer(256),
  view: new Uint8Array([1, 2, 3, 4, 5])
};

const copy = structuredClone(binaryData);
// Оба ArrayBuffer остаются независимыми

6. Ограничения Structured Clone

Некоторые типы НЕ могут быть клонированы:

// Это вызовет ошибку DOMException
try {
  // Функции
  const fn = () => 'hello';
  const clone1 = structuredClone({ fn }); // ❌ Ошибка!
  
  // DOM элементы
  const div = document.getElementById('app');
  const clone2 = structuredClone({ div }); // ❌ Ошибка!
  
  // WeakMap, WeakSet
  const weakMap = new WeakMap();
  const clone3 = structuredClone({ weakMap }); // ❌ Ошибка!
} catch (e) {
  console.error('Cannot clone:', e.message);
}

7. Производительность

// Structured Clone работает со сложными объектами
const largeObject = {
  data: Array.from({ length: 10000 }, (_, i) => ({
    id: i,
    nested: { value: Math.random() },
    date: new Date()
  }))
};

const start = performance.now();
const clone = structuredClone(largeObject);
const end = performance.now();

console.log(`Clone took ${end - start}ms`);
// Обычно быстро, но для очень больших объектов может быть медленнее JSON

8. Случаи использования

// 1. State Management
const newState = structuredClone(currentState);
newState.user.email = newEmail;
dispatch({ type: 'UPDATE_USER', payload: newState });

// 2. Undo/Redo механизм
const history = [];
const currentData = { /* объект */ };
history.push(structuredClone(currentData)); // Сохраняем снимок

// 3. Отправка данных в Web Worker
const workerData = structuredClone(largeData);
worker.postMessage({ data: workerData });

// 4. Кэширование результатов
const cache = new Map();
const key = 'api_response';
const data = { /* данные с сервера */ };
cache.set(key, structuredClone(data)); // Кэшируем копию

// 5. Форма для редактирования
const originalData = { name: 'John', email: 'john@example.com' };
const editingData = structuredClone(originalData);
// Пользователь редактирует editingData
// Если нажать "Отмена" - просто забыть editingData

Итоговые рекомендации

  • Используй structuredClone() для глубокого копирования объектов
  • Это лучше чем JSON.stringify, так как сохраняет типы данных
  • Помни об ограничениях: функции, DOM элементы, WeakMap/WeakSet не копируются
  • Идеально для Redux, state management и работы с копиями данных
  • Для очень простых объектов можно использовать Object.assign, но для вложенных объектов используй structuredClone