Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Функція structuredClone()». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`structuredClone()`, це вбудована функція, яка створює глибоку копію (deep clone) значення разом з усіма вкладеними рівнями.** Вона розуміє не лише звичайні об'єкти та масиви, а й `Date`, `Map`, `Set`, `RegExp`, `Error`, `ArrayBuffer`, `Blob`, `File`, типізовані масиви, `undefined`, `NaN`, `Infinity` і навіть циклічні посилання. Повернений об'єкт повністю незалежний від оригіналу, тому зміна вкладеного поля копії не зачіпає джерело. Це безпечна заміна старому прийому `JSON.parse(JSON.stringify(obj))`, який перетворює `Date` на рядок, губить `Map`, `Set`, `undefined` та `RegExp`, замінює `NaN` на `null` і падає на циклічних посиланнях. Функцію не можна застосувати до функцій і DOM-елементів, у таких випадках буде `DataCloneError`. Доступна в сучасних браузерах і в Node.js починаючи з версії 17. ```javascript const user = { name: 'Tim', meta: { active: true } }; const copy = structuredClone(user); copy.meta.active = false; console.log(user.meta.active); // true, оригінал не змінився ``` **Ключове:** `structuredClone()`, це вбудований надійний deep clone, який зберігає типи та циклічні посилання, але не копіює функції та DOM-вузли.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**`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 і нижче функції немає, там потрібен поліфіл або власна реалізація.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.