Skip to main content

Функція structuredClone()

structuredClone(), це вбудована функція JavaScript, яка створює глибоку копію (deep clone) будь-якого значення, включно з об'єктами, масивами, Map, Set, датами, RegExp, Blob, File, ArrayBuffer і навіть циклічними посиланнями. Результат, це повністю незалежна копія, а не ще одне посилання на той самий об'єкт.

Теорія

TL;DR

  • structuredClone(value) повертає новий незалежний глибокий клон значення.
  • Зберігає Date, Map, Set, RegExp, Error, ArrayBuffer, Blob, File, undefined, NaN, Infinity.
  • Коректно обробляє циклічні посилання, на яких JSON.stringify() кидає помилку.
  • Не вміє копіювати функції, класи з методами та DOM-елементи, буде DataCloneError.
  • Другий аргумент { transfer: [...] } дозволяє передати бінарний буфер замість копіювання.
  • Працює в сучасних браузерах і в Node.js починаючи з версії 17.

Швидкий приклад

javascript
const user = { name: "Tim", age: 25, skills: ["JS", "React"], meta: { active: true }, }; const copy = structuredClone(user); copy.meta.active = false; console.log(user.meta.active); // true, оригінал не змінився

Тут structuredClone() створив нову копію, а не посилання на той самий об'єкт, на відміну від поверхневого копіювання через { ...user }, де meta залишилася б спільною.

Синтаксис

javascript
const clone = structuredClone(value);
  • value, це те, що потрібно склонувати;
  • функція повертає новий, повністю скопійований і незалежний об'єкт.

Клонування рекурсивне: кожен вкладений об'єкт, масив чи колекція теж отримує власну копію, тому змінювати клон можна як завгодно глибоко.

Головна відмінність від JSON.parse(JSON.stringify(...))

Раніше для глибокого копіювання часто писали так:

javascript
const copy = JSON.parse(JSON.stringify(obj));

Але в цього способу багато обмежень:

Тип данихJSON методstructuredClone
Dateперетворюється на рядокзберігається як Date
Map, Setгублятьсякопіюються
undefinedзникаєзберігається
RegExp, Errorгублятьсязберігаються
NaN, Infinityперетворюються на nullзберігаються
Циклічні посиланняпомилкапідтримуються

Тобто structuredClone(), це надійний і безпечний аналог deep clone, який підтримує всі ці типи.

Приклад з циклічними посиланнями

javascript
const obj = {}; obj.self = obj; // циклічне посилання const clone = structuredClone(obj); console.log(clone.self === clone); // true

Раніше таке клонування просто викликало б помилку. Алгоритм structured clone запам'ятовує вже скопійовані об'єкти, тому повторне входження в той самий вузол перетворюється на посилання всередині копії, а не на нескінченну рекурсію.

Клонування з передачею бінарних даних

У structuredClone є другий аргумент, об'єкт опцій, який дозволяє передати (а не скопіювати) деякі об'єкти, наприклад ArrayBuffer.

javascript
const buffer = new ArrayBuffer(8); const clone = structuredClone(buffer, { transfer: [buffer] }); console.log(buffer.byteLength); // 0, оригінал передано і відключено console.log(clone.byteLength); // 8, дані тепер у клона

Це працює схоже на transferable-об'єкти в postMessage: пам'ять не копіюється, а змінює власника, тому операція дешева навіть для великих буферів.

Де працює і підсумок

Функція підтримується в усіх сучасних браузерах і в Node.js, починаючи з версії 17:

javascript
structuredClone({ test: true }); // працює в Node.js 17+
ПунктОпис
Що робитьГлибоко клонує значення майже будь-якого типу
ПовертаєПовну незалежну копію
ПідтримуєDate, Map, Set, RegExp, ArrayBuffer, циклічні посилання
Не підтримуєФункції, DOM-елементи
СумісністьСучасні браузери та Node.js 17+
АналогБезпечна альтернатива JSON.parse(JSON.stringify())

Типові помилки

  • Очікувати, що скопіюються методи. Функції не клонуються: structuredClone({ fn() {} }) кидає DataCloneError. Клас перетворюється на звичайний об'єкт із даними без прототипу.
  • Клонувати DOM-вузли. structuredClone(document.body) теж кидає DataCloneError, вузли документа не серіалізуються цим алгоритмом.
  • Плутати з поверхневою копією. { ...obj } і Object.assign({}, obj) копіюють лише верхній рівень, вкладені об'єкти залишаються спільними.
  • Забувати про прототип. Клон отримує звичайний Object.prototype, тому copy instanceof User дасть false.
  • Розраховувати на збереження геттерів і сеттерів. Вони обчислюються один раз, у клон потрапляє вже готове значення як звичайна властивість.
  • Використовувати в старому середовищі. У Node.js 16 і нижче функції немає, там потрібен поліфіл або власна реалізація.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.