Spread operator ... (ES6) tạo shallow copy mảng — ngắn gọn, dễ đọc hơn slice().
Cách 1: slice() — Cổ điển
<script>
const games = ['cricket', 'hockey', 'football', 'kabaddi'];
const cloneGames = games.slice(); // Không tham số = copy all
document.write(cloneGames); // cricket,hockey,football,kabaddi
</script>
Cách 2: Spread Operator — Hiện đại (Khuyên dùng)
<script>
const games = ['cricket', 'hockey', 'football', 'kabaddi'];
const cloneGames = [...games]; // Spread vào mảng mới
document.write(cloneGames); // cricket,hockey,football,kabaddi
</script>
Shallow Copy — Lưu ý quan trọng
Cả slice() và ... chỉ copy level 1. Nested object/array vẫn shared reference.
const original = [{ id: 1 }, { id: 2 }];
const clone = [...original];
clone[0].id = 99;
console.log(original[0].id); // 99 — MUTATED! (shared reference)
clone.push({ id: 3 }); // Chỉ ảnh hưởng clone
console.log(original.length); // 2 — OK
Deep Clone — Các cách
| Phương pháp | Hỗ trợ | Lưu ý |
|---|---|---|
JSON.parse(JSON.stringify(arr)) | Plain object, array, primitive | Mất function, Date, RegExp, Map, Set, circular ref |
structuredClone(arr) | Hầu hết kiểu built-in (Date, RegExp, Map, Set, Blob, File...), circular ref | Modern browsers (Chrome 98+, FF 94+, Safari 15.4+), Node 17+ |
Lodash _.cloneDeep() | Tùy chỉnh được, hỗ trợ nhiều kiểu | Cần dependency, chậm hơn structuredClone |
| Custom recursive | Kiểm soát hoàn toàn | Phức tạp, dễ bug |
Ví dụ structuredClone (Best modern)
const original = [
{ id: 1, date: new Date('2024-01-01') },
{ id: 2, tags: new Set(['a', 'b']) }
];
const deepClone = structuredClone(original);
deepClone[0].date.setFullYear(2025);
console.log(original[0].date.getFullYear()); // 2024 — KHÔNG bị ảnh hưởng
Khi nào dùng cái nào?
- Mảng primitive / flat object →
[...arr](nhanh, sạch). - Cần deep clone, modern env →
structuredClone(). - Legacy browser / custom logic →
_.cloneDeep()hoặcJSON.parse(JSON.stringify())(cẩn thận limitation).