JAVASCRIPT WEB-DEVELOPMENT PROGRAMMING DATA-MANAGEMENT IMMUTABILITY MODERN-JAVASCRIPT BEST-PRACTICES DEVELOPER-EXPERIENCE BROWSER-API PERFORMANCE

Structured Clone: Jurus Rahasia Deep Copy Objek Kompleks di JavaScript Modern

⏱️ 8 menit baca
👨‍💻

Structured Clone: Jurus Rahasia Deep Copy Objek Kompleks di JavaScript Modern

1. Pendahuluan

Sebagai developer web, kita sering berhadapan dengan objek dan data. Baik itu state di aplikasi frontend React/Vue/Angular, konfigurasi di backend Node.js, atau data yang diambil dari API, kita perlu memanipulasi dan mengelola data tersebut dengan aman. Salah satu operasi yang terlihat sederhana namun seringkali menimbulkan bug aneh adalah “deep copy” objek.

Berapa banyak dari kita yang pernah menggunakan JSON.parse(JSON.stringify(obj)) untuk menduplikasi objek? 🙋‍♂️ Saya yakin banyak. Jurus ini memang cepat dan mudah di awal, tetapi ia punya banyak keterbatasan yang bisa jadi bom waktu di aplikasi Anda. Data seperti Date, RegExp, Map, Set, atau bahkan fungsi dan DOM nodes akan hilang atau terkorupsi dengan metode ini.

Untungnya, JavaScript modern hadir dengan solusi yang lebih elegan dan robust: structuredClone(). Fungsi global yang diperkenalkan di ES2022 ini adalah jurus rahasia yang mungkin belum banyak developer tahu, tapi sangat powerful untuk deep copy objek kompleks dengan benar dan aman.

Artikel ini akan membahas tuntas mengapa structuredClone() adalah pilihan terbaik untuk deep copy di JavaScript, apa saja yang bisa ia lakukan, dan bagaimana menggunakannya secara efektif dalam proyek Anda. Mari kita selami!

2. Apa itu Deep Copy dan Kenapa Penting?

Sebelum masuk ke structuredClone(), mari kita pahami dulu perbedaan antara shallow copy dan deep copy.

📌 Shallow Copy (Salinan Dangkal) Ketika Anda melakukan shallow copy, Anda membuat salinan objek atau array baru, tetapi elemen-elemen di dalamnya (jika berupa objek atau array lain) masih merujuk ke lokasi memori yang sama dengan objek aslinya.

Contoh:

const original = {
  nama: "Budi",
  alamat: {
    jalan: "Jl. Merdeka",
    nomor: 10
  },
  hobi: ["coding", "membaca"]
};

const shallowCopy = { ...original }; // Shallow copy menggunakan spread operator

shallowCopy.nama = "Andi";
shallowCopy.alamat.nomor = 12; // ⚠️ Ini akan mengubah original.alamat.nomor juga!
shallowCopy.hobi.push("bersepeda"); // ⚠️ Ini akan mengubah original.hobi juga!

console.log(original.nama); // Budi
console.log(original.alamat.nomor); // 12 (Berubah!)
console.log(original.hobi); // ["coding", "membaca", "bersepeda"] (Berubah!)

Seperti yang Anda lihat, perubahan pada alamat.nomor dan hobi di shallowCopy ikut memengaruhi original. Ini bisa menyebabkan bug yang sulit dilacak, terutama dalam aplikasi dengan manajemen state yang kompleks.

🎯 Deep Copy (Salinan Mendalam) Deep copy, di sisi lain, membuat salinan objek yang sepenuhnya independen dari objek aslinya. Semua objek bersarang (nested objects) juga disalin secara rekursif, sehingga tidak ada referensi yang berbagi memori.

💡 Kenapa Deep Copy Penting?

3. Keterbatasan JSON.parse(JSON.stringify()): Bom Waktu yang Tersembunyi

Sebelum structuredClone(), JSON.parse(JSON.stringify(obj)) adalah jurus andalan banyak developer untuk deep copy. Mari kita lihat mengapa ini adalah solusi yang tidak ideal:

const userProfile = {
  id: 1,
  username: "johndoe",
  lastLogin: new Date(), // Objek Date
  settings: {
    theme: "dark",
    notifications: true
  },
  greet: function() { console.log("Hello!"); }, // Fungsi
  status: undefined, // undefined
  regExp: /abc/g, // Objek RegExp
  dataMap: new Map([['key', 'value']]), // Objek Map
  dataArrayBuffer: new ArrayBuffer(8) // Objek ArrayBuffer
};

const jsonCopy = JSON.parse(JSON.stringify(userProfile));

console.log(jsonCopy.lastLogin); // String, bukan objek Date!
console.log(jsonCopy.greet); // undefined (Fungsi hilang!)
console.log(jsonCopy.status); // undefined (Benar, tapi jika ada property lain yang hilang?)
console.log(jsonCopy.regExp); // {} (Objek kosong, bukan RegExp!)
console.log(jsonCopy.dataMap); // {} (Objek kosong!)
console.log(jsonCopy.dataArrayBuffer); // {} (Objek kosong!)

❌ Masalah utama JSON.parse(JSON.stringify()):

  1. Kehilangan Fungsi: Fungsi tidak dapat diserialisasi ke JSON, jadi akan hilang.
  2. Kehilangan undefined: Properti dengan nilai undefined akan diabaikan.
  3. Transformasi Date: Objek Date akan diubah menjadi string ISO 8601, bukan objek Date yang valid.
  4. Transformasi RegExp: Objek RegExp akan menjadi objek kosong {}.
  5. Transformasi Map dan Set: Objek Map dan Set akan menjadi objek kosong {}.
  6. Transformasi ArrayBuffer, TypedArray, Blob, File, ImageData: Objek-objek ini juga akan menjadi objek kosong {}.
  7. Tidak bisa menyalin DOM Nodes.
  8. Tidak bisa menyalin objek dengan referensi sirkular (circular references). Ini akan menyebabkan error Converting circular structure to JSON.

Jelas, JSON.parse(JSON.stringify()) bukanlah solusi deep copy yang universal dan aman.

4. Memperkenalkan structuredClone(): Sang Penyelamat

structuredClone() adalah fungsi global yang dirancang khusus untuk membuat deep copy dari nilai JavaScript. Ia menggunakan algoritma structured cloning, mekanisme yang sama yang digunakan oleh Web Workers untuk mengirim pesan antar thread, dan juga oleh IndexedDB untuk menyimpan data.

✅ Sintaks Dasar:

const newObject = structuredClone(originalObject);

Mari kita coba lagi contoh userProfile dengan structuredClone():

const userProfile = {
  id: 1,
  username: "johndoe",
  lastLogin: new Date(),
  settings: {
    theme: "dark",
    notifications: true
  },
  greet: function() { console.log("Hello!"); }, // Fungsi
  status: undefined,
  regExp: /abc/g,
  dataMap: new Map([['key', 'value']]),
  dataArrayBuffer: new ArrayBuffer(8)
};

const structuredCopy = structuredClone(userProfile);

// Perubahan pada salinan tidak memengaruhi asli
structuredCopy.settings.theme = "light";
structuredCopy.dataMap.set('newKey', 'newValue');

console.log(userProfile.settings.theme); // dark (Tidak berubah!)
console.log(userProfile.dataMap.get('newKey')); // undefined (Tidak berubah!)

// Tipe data kompleks tetap terjaga
console.log(structuredCopy.lastLogin instanceof Date); // true
console.log(structuredCopy.regExp instanceof RegExp); // true
console.log(structuredCopy.dataMap instanceof Map); // true
console.log(structuredCopy.dataArrayBuffer instanceof ArrayBuffer); // true

// Fungsi dan undefined tetap memiliki batasan
console.log(structuredCopy.greet); // undefined (Fungsi tetap hilang, ini memang batasan structured cloning)
console.log(structuredCopy.status); // undefined (Status undefined tetap dipertahankan)

⚠️ Penting: Meskipun structuredClone() sangat powerful, ia juga memiliki batasan yang sama dengan algoritma structured cloning secara umum:

5. Kekuatan structuredClone(): Mengatasi Tipe Data Kompleks

Inilah daftar tipe data yang dapat di-clone dengan structuredClone() yang tidak bisa ditangani oleh JSON.parse(JSON.stringify()):

const objWithCircularRef = {};
objWithCircularRef.self = objWithCircularRef;

try {
  JSON.parse(JSON.stringify(objWithCircularRef));
} catch (e) {
  console.log("❌ JSON.stringify gagal karena referensi sirkular:", e.message);
}

const clonedCircular = structuredClone(objWithCircularRef);
console.log("✅ structuredClone berhasil meng-clone referensi sirkular.");
console.log(clonedCircular.self === clonedCircular); // true (referensi sirkular dipertahankan dalam salinan)

Ini adalah game changer untuk deep copy, karena Anda tidak perlu khawatir lagi tentang detail implementasi atau tipe data aneh yang bisa merusak salinan Anda.

6. Tips dan Best Practices Penggunaan structuredClone()

// Contoh penggunaan dalam konteks state management (pseudo-code React)
function reducer(state, action) {
  switch (action.type) {
    case 'UPDATE_USER_SETTINGS':
      const newSettings = structuredClone(state.user.settings);
      newSettings.theme = action.payload.theme;
      return {
        ...state,
        user: {
          ...state.user,
          settings: newSettings
        }
      };
    default:
      return state;
  }
}

Dalam contoh di atas, kita memastikan newSettings adalah salinan yang sepenuhnya terpisah, sehingga perubahan tidak akan memutasi state asli secara langsung, menjaga prinsip immutability.

Kesimpulan

structuredClone() adalah tambahan yang sangat berharga untuk toolkit JavaScript modern. Ia menyelesaikan masalah deep copy objek kompleks dengan cara yang robust, efisien, dan mendukung berbagai tipe data yang sebelumnya sulit ditangani. Dengan memahami kekuatan dan batasannya, Anda bisa menulis kode yang lebih aman, prediktif, dan mudah di-maintain.

Lupakan JSON.parse(JSON.stringify()) untuk deep copy objek kompleks Anda. Saatnya beralih ke structuredClone() dan nikmati kemudahan serta keandalan yang ditawarkannya!

🔗 Baca Juga