Як клонувати (копіювати) об’єкт і масив у JavaScript
Клонування масиву
1. Використання оператору spread (...):
const originalArray = [1, 2, 3]; const clonedArray = [...originalArray]; console.log(clonedArray); // Output: [1, 2, 3]
2. Використання Array.prototype.slice():
const originalArray = [1, 2, 3]; const clonedArray = originalArray.slice(); console.log(clonedArray); // Output: [1, 2, 3]
3. Використання Array.from():
const originalArray = [1, 2, 3]; const clonedArray = Array.from(originalArray); console.log(clonedArray); // Output: [1, 2, 3]
4. Використання structuredClone() (глибоке клонування):
const originalArray = [1, { key: "value" }];
const clonedArray = structuredClone(originalArray);
console.log(clonedArray); // Output: [1, { key: "value" }]
Клонування об’єкта
1. Використання оператору spread (...):
const originalObject = { a: 1, b: 2 };
const clonedObject = { ...originalObject };
console.log(clonedObject); // Output: { a: 1, b: 2 }
2. Використання Object.assign():
const originalObject = { a: 1, b: 2 };
const clonedObject = Object.assign({}, originalObject);
console.log(clonedObject); // Output: { a: 1, b: 2 }
3. Використання structuredClone() (глибоке клонування):
const originalObject = { a: 1, b: { c: 2 } };
const clonedObject = structuredClone(originalObject);
console.log(clonedObject); // Output: { a: 1, b: { c: 2 } }
4. Використання JSON.parse() та JSON.stringify() (глибоке клонування):
const originalObject = { a: 1, b: { c: 2 } };
const clonedObject = JSON.parse(JSON.stringify(originalObject));
console.log(clonedObject); // Output: { a: 1, b: { c: 2 } }
Цей метод не підтримує функції, undefined, Symbol або циклічні посилання.
Глибоке клонування проти поверхневого клонування
- Поверхнев клонування (наприклад, за допомогою
...,slice()абоObject.assign()):
Клонує лише перший рівень об’єкта або масиву. Вкладені об’єкти або масиви залишаються посиланнями на оригінал. - Глибоке клонування (наприклад,
structuredClone()абоJSON.parse(JSON.stringify())):
Клонує всю структуру, включаючи вкладені об’єкти чи масиви.
Коли використовувати кожен метод
- Використовуйте поверхневе клонування для простих структур.
- Використовуйте глибоке клонування, якщо об’єкт або масив містить вкладені структури, і вам потрібно уникати посилань на вихідні дані.
Клонування масиву або об’єкта, який містить методи (функції)
Поверхневе клонування
Використання оператора spread (...) або Object.assign()
- Функції в об’єкті чи масиві обробляються як будь-яка інша властивість.
- Посилання на функцію копіюється до клонованого об’єкта чи масиву.
- Оригінальна та клонована версії використовуватимуть ту саму функцію в пам’яті.
const originalObject = {
value: 42,
method: function () {
return this.value;
}
};
const clonedObject = { ...originalObject };
console.log(clonedObject.method()); // Output: 42
console.log(clonedObject.method === originalObject.method); // Output: true (same reference)
Для масивів: якщо масив містить функції, посилання на ці функції копіюються. Використання оператора розширення (...) або slice()
const originalArray = [1, 2, function () { return 42; }];
const clonedArray = [...originalArray];
console.log(clonedArray[2]()); // Output: 42
console.log(clonedArray[2] === originalArray[2]); // Output: true (same reference)
Глибоке клонування
Використання JSON.parse(JSON.stringify())
- Методи (функції) буде втрачено, оскільки JSON підтримує лише серіалізовані типи даних (наприклад, числа, рядки, масиви та об’єкти).
- Будь-які властивості, що містять функції, не існуватимуть у клонованому об’єкті чи масиві.
const originalObject = {
value: 42,
method: function () {
return this.value;
}
};
const clonedObject = JSON.parse(JSON.stringify(originalObject));
console.log(clonedObject.method); // Output: undefined
Використання structuredClone() (Глибоке клонування)
Функції не клонуються. Структуроване клонування не підтримує функції та видаляє їх із клонованого об’єкта чи масиву.
const originalObject = {
value: 42,
method: function () {
return this.value;
}
};
const clonedObject = structuredClone(originalObject);
console.log(clonedObject.method); // Output: undefined
Ключові моменти, про які слід пам’ятати
1. Поверхневе клонування:
- Функції копіюються за посиланням, тобто клоновані та вихідні об’єкти/масиви використовуватимуть ту саму функцію.
2. Глибоке клонування:
- Функції зазвичай втрачаються (видаляються) під час використання таких методів, як
JSON.parse(JSON.stringify())абоstructuredClone(), оскільки їх не можна серіалізувати. li>
3. Якщо вам потрібно клонувати об’єкт або масив за допомогою методів, вам може знадобитися написати спеціальну функцію клонування для явної обробки функцій або використовувати сторонні бібліотеки.
Власне клонування для об’єктів із методами
Ви можете керувати функціями вручну у своїй логіці клонування:
function customClone(obj) {
const clone = Array.isArray(obj) ? [] : {};
for (const key in obj) {
if (typeof obj[key] === 'function') {
clone[key] = obj[key]; // Copy functions by reference
} else if (typeof obj[key] === 'object' && obj[key] !== null) {
clone[key] = customClone(obj[key]); // Recursively clone objects
} else {
clone[key] = obj[key]; // Copy primitives
}
}
return clone;
}
const original = {
value: 42,
method() {
return this.value;
}
};
const cloned = customClone(original);
console.log(cloned.method()); // Output: 42
console.log(cloned.method === original.method); // Output: true (same reference)
Цей підхід гарантує збереження функцій при глибокому клонуванні інших властивостей.
Використання сторонніх бібліотек
У проектах я часто використовую Lodash або jQuery. Обидві ці бібліотеки мають методи глибокого клонування. Під час використання Lodash або jQuery для виконання глибокого клонування обидві бібліотеки обробляють функції по-іншому, ніж такі нативні методи, як JSON.parse(JSON.stringify()) або structuredClone().
Глибоке клонування за допомогою Lodash
Використання Lodash _.cloneDeep():
- Lodash виконує глибоке клонування об’єкта або масиву, включаючи вкладені структури.
- Функції (методи) в об’єкті чи масиві копіюються за посиланням. Це означає, що функція в клонованому об’єкті чи масиві вказуватиме на те саме посилання на пам’ять, що й оригінал.
const _ = require('lodash');
const originalObject = {
value: 42,
method: function () {
return this.value;
}
};
const clonedObject = _.cloneDeep(originalObject);
console.log(clonedObject.method()); // Output: 42
console.log(clonedObject.method === originalObject.method); // Output: true (same reference)
Lodash не видаляє функції, на відміну від JSON.parse(JSON.stringify()), але він не створює нову копію функції. Він зберігає посилання на оригінал.
Глибоке клонування за допомогою jQuery
Використання $.extend() jQuery:
$.extend()jQuery використовується для клонування об’єктів. Щоб отримати глибокий клон, ви передаєте true як перший аргумент.- Як і Lodash, jQuery копіює функції за посиланням.
const originalObject = {
value: 42,
method: function () {
return this.value;
}
};
const clonedObject = $.extend(true, {}, originalObject);
console.log(clonedObject.method()); // Output: 42
console.log(clonedObject.method === originalObject.method); // Output: true (same reference)
Обмеження $.extend():
- Механізм клонування jQuery простіший і менш надійний порівняно з Lodash.
- Він не обробляє деякі складні випадки використання (наприклад, циклічні посилання) так ефективно, як Lodash.
Схожі записи:
-
Як визначити напрямок прокручування (скроллу) на сторінці за допомогою JavaScript
Іноді необхідно визначити напрямок вертикального прокручування (скроллу) на веб-сайті, щоб динамічно змінювати поведінку елементів інтерфейсу. Наприклад, це може бути кор...
-
Swipe події на сенсорних пристроях у JavaScript
Кожен день сенсорні пристрої впроваджуються в наше життя. Ці пристрої мають певні події, на відміну від настільного комп’ютера. Однією з таких подій є swipe (свайп). Особ...
-
Як отримати максимальне значення в масиві JavaScript
Коротка замітка про пошук максимального значення в масиві JavaScript із числовими значеннями. Об’єкт Array в JS не має власного методу max. Щоб знайти максимальне знач...
Залишити відповідь