Menu

Object Spread di JavaScript: Clone, Merge, dan Override

Cara kerja operator spread pada object di JavaScript: clone, merge, override property, dan jebakan shallow copy yang sering membuat orang tersandung.

Halaman ini dilengkapi editor yang bisa dijalankan. Edit, jalankan, dan lihat output-nya seketika.

Spread membentangkan object ke object lain

Sintaks object spread, yaitu tiga titik di depan sebuah object, menyalin property enumerable milik object itu sendiri ke object literal di sekitarnya. Inilah jalan terpendek untuk clone, merge, dan membuat salinan yang sudah diubah tanpa menyentuh object aslinya.

copy punya key dan nilai yang sama seperti user, tapi ia object yang berbeda. Mengubah salah satunya tidak memengaruhi yang lain, setidaknya di tingkat atas. Kita akan kembali ke catatan ini sebentar lagi.

Cara memikirkannya: { ...obj } berarti "tuangkan property obj ke object literal baru ini." Apa pun yang kamu tulis di samping spread ikut menjadi bagian dari hasilnya.

Clone dan override dalam satu langkah

Pola yang paling umum adalah melakukan spread pada sebuah object, lalu menambahkan atau menimpa beberapa property. Key yang ditulis belakangan yang menang, jadi tulis spread lebih dulu dan override sesudahnya:

user tidak tersentuh. updated adalah object baru dengan role yang sudah diganti. Pola update immutable ini muncul di mana-mana dalam JavaScript modern: state updater di React, reducer di Redux, dan kode apa pun yang lebih suka tidak mengubah data di tempat.

Balik urutannya, dan kamu mendapat perilaku sebaliknya:

Di sini role: "guest" ditulis lebih dulu, jadi user.role menimpanya. Ini berguna saat kamu ingin nilai default yang bisa ditimpa oleh object yang di-spread.

Menggabungkan object

Spread dua object (atau lebih) ke literal baru untuk menggabungkannya. Kalau ada key yang bentrok, object yang belakangan menimpa object sebelumnya:

theme dan fontSize berasal dari userPrefs; debug lolos dari defaults. Tiga object? Empat? Aturannya sama: baca dari kiri ke kanan, tulisan terakhir yang menang.

Ini pengganti modern untuk Object.assign({}, defaults, userPrefs). Keduanya melakukan hal yang sama, tapi versi spread lebih mudah dibaca dan tidak menggoda kamu ke bug umum menulis Object.assign(defaults, userPrefs), yang mengubah defaults.

Spread adalah shallow copy

Bagian inilah yang sering menjebak orang. Spread menyalin property tingkat atas dari sebuah object. Kalau nilai sebuah property juga berupa object atau array, yang disalin adalah referensinya, bukan isinya.

Mengubah copy.address.city ikut mengubah user.address.city, karena kedua object memakai object address yang sama. Spread hanya memberi kita pembungkus luar yang baru.

Kalau kamu perlu mengubah sesuatu yang bersarang, lakukan spread pada setiap tingkat yang ingin kamu ubah:

Untuk deep clone sungguhan dari data apa pun, pakai structuredClone(obj). Fungsi ini menangani object bersarang, array, tanggal, map, dan set, dan sudah tersedia di setiap runtime modern.

Spread vs. rest

Keduanya memakai tiga titik yang sama, tapi melakukan hal yang berlawanan. Spread membentangkan; rest mengumpulkan.

Patokannya: kalau ... ada di sisi kiri = (destructuring), itu rest. Kalau ada di dalam object atau array literal di sisi kanan, itu spread.

Menghapus property secara immutable

Menggabungkan rest destructuring dengan spread memberi cara yang rapi untuk membuat salinan object dengan satu key dihapus, tanpa delete dan tanpa mutasi:

tempToken ditarik keluar ke variabelnya sendiri (yang kamu abaikan), dan sisanya masuk ke safe. user yang asli tidak tersentuh.

Yang tidak disalin oleh spread

Beberapa detail halus yang perlu kamu tahu:

  • Property non-enumerable tidak disalin. Sebagian besar property yang kamu buat bersifat enumerable secara default, tapi property yang didefinisikan dengan Object.defineProperty dan beberapa bawaan tidak.
  • Prototype tidak disalin. { ...instance } memberimu object biasa, bukan instance dari class aslinya. Method yang didefinisikan di prototype class tidak akan ada di salinannya.
  • Getter dievaluasi. Melakukan spread pada object yang punya getter akan memanggil getter itu sekali dan menyimpan nilai kembaliannya sebagai property biasa di object baru.

copy punya x dan y, tapi ia object biasa: distance tinggal di Point.prototype, yang tidak disentuh oleh spread. Kalau kamu perlu clone instance sebuah class, biasanya class itu harus menyediakan method clone sendiri.

Berikutnya: method array

Spread adalah satu bagian dari perkakas data immutable. Bagian besar lainnya adalah method array, seperti map, filter, reduce, dan kawan-kawannya, yang menghasilkan array baru alih-alih mengubah array aslinya. Itulah halaman berikutnya.

Pertanyaan yang sering diajukan

Apa fungsi ...obj di JavaScript?

Di dalam object literal, ...obj menyalin semua property enumerable milik object itu sendiri ke object baru. { ...user } menghasilkan object baru dengan key dan nilai yang sama seperti user. Ini cara standar untuk clone atau menggabungkan object tanpa mengubah object aslinya.

Bagaimana cara menggabungkan dua object di JavaScript?

Spread keduanya ke object literal baru: const merged = { ...a, ...b }. Property dari b menimpa key yang sama dari a, karena property yang ditulis belakangan yang menang. Ini setara dengan Object.assign({}, a, b), tapi lebih mudah dibaca.

Apakah object spread menghasilkan deep copy?

Tidak. Object spread adalah shallow copy: yang disalin hanya property tingkat atas, sedangkan object dan array bersarang tetap dipakai bersama lewat referensi. Mengubah copy.address.city juga akan mengubah original.address.city. Untuk deep copy yang sebenarnya, pakai structuredClone(obj).

Apa bedanya spread dan rest?

Bentuknya sama persis (...), tapi tugasnya berlawanan. Spread membentangkan object atau array menjadi property atau elemen terpisah: { ...user }. Rest mengumpulkan sisanya ke satu variabel: const { name, ...others } = user. Konteksnya yang memberi tahu mana yang sedang kamu lihat.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai