Soal 1Tulis const backup = order;, lalu jalankan backup.total = 0;. Apa yang terjadi pada order.total?
Reference dan Copying — Jebakan Array dan Object
Pelajari kenapa array dan object yang di-assign saling menunjuk, lalu cara menyalinnya dengan benar.
Coba backup sebuah order sebelum mengeditnya dengan menulis const backup = order;, dan memperbaiki order belakangan mengubah backup juga. Ini tidak pernah terjadi pada number atau string.
Artikel ini membahas apa yang sebenarnya diteruskan saat kamu meng-assign array atau object, dan cara membangun copy yang aman.
Apa yang Diteruskan Assignment — Primitive vs Reference
Yang bikin ketidakcocokan ini susah dilacak adalah apa yang diteruskan saat assignment berbeda tergantung jenis value-nya. Di sini kita rangkum apa yang tersalin apa adanya saat assignment, dan apa yang tidak.
5 jenis — number, string, boolean, null, dan undefined (disebut primitive — value yang bukan object maupun array) — mendapat value-nya sendiri yang di-copy saat kamu meng-assign-nya.
Kedua variable-nya tidak berhubungan lagi setelah copy itu, jadi mengubah satu tidak pernah mengubah yang lain.
Array dan object adalah reference type (type yang menyimpan informasi yang menunjuk ke tempat sebuah value hidup, alih-alih value itu sendiri). Assignment cuma meneruskan informasi lokasi itu, jadi 2 variable berujung menunjuk ke array atau object yang persis sama.
Tulis ulang lewat nama mana pun, dan kamu menulis ulang hal yang sama persis, tidak peduli lewat mana.
// Primitive dapat value-nya sendiri yang di-copy
let price = 3980;
let salePrice = price;
salePrice = 2980;
console.log(price); // 3980 (tidak terpengaruh)
console.log(salePrice); // 2980
// Array menunjuk ke 1 hal yang sama
const cart = ["A4 Notebook"];
const savedCart = cart;
savedCart.push("Permanent Marker");
console.log(cart.length); // 2 (cart ikut bertambah)
console.log(cart === savedCart); // true (keduanya menunjuk ke hal yang sama)
Bahkan dengan const, Isinya Bisa Ditulis Ulang
Yang dikunci const cuma di mana variable-nya menunjuk. Tulis const cart = [];, lalu cart.push("Permanent Marker"), dan isinya bertambah; const order = {}, lalu order.total = 0, juga berhasil.
Yang dilarang cuma reassignment yang menunjuknya ke tempat lain sama sekali, seperti cart = [...].
Membangun Copy — Apa yang Sebenarnya Dilihat ===
Seperti yang baru kamu lihat, assignment saja nggak menghasilkan copy yang aman dan terpisah dari aslinya. Mau order terpisah dengan cuma amount-nya yang diubah, membiarkan aslinya tidak tersentuh? Bangun object baru yang menata isinya dengan spread syntax, seperti { ...order }. Yang layak dipastikan adalah hubungan antara apa yang kamu bangun dan aslinya.
const copiedOrder = { ...order }; membangun object terpisah, jadi order === copiedOrder adalah false. Untuk array dan object, === mengecek bukan apakah isinya cocok, tapi apakah keduanya persis 1 hal yang sama.
Untuk membandingkan isinya, tuliskan sendiri hal spesifik yang mau kamu bandingkan — jumlah key, value individual, dan sebagainya.
true saat keduanya menunjuk ke hal yang sama, dan false untuk yang dibangun terpisah, bahkan dengan isi yang identik.const cart = ["A4 Notebook"];
const copiedCart = [...cart];
// Hal yang terpisah, jadi === adalah false
console.log(cart === copiedCart); // false
// Bahkan dengan isi identik, tetap false
console.log(["A"] === ["A"]); // false
// Bandingkan isinya sendiri, dan itu true
console.log(cart[0] === copiedCart[0]); // true
// Cuma true saat keduanya menunjuk ke hal yang sama
const savedCart = cart;
console.log(cart === savedCart); // true
Copying Tidak Mencapai Value Nested — Shallow vs Deep Copy
Spread syntax sejauh ini sudah menghasilkan copy yang aman untuk value primitif seperti amount. Tapi copy sebuah order dengan object nested, seperti data customer, dan meski object terluarnya jadi terpisah, yang di dalamnya masih menunjuk ke hal yang persis sama seperti aslinya. Perbaiki sebuah address di apa yang kamu kira copy-nya, dan address order aslinya ikut berubah — ketidakcocokan yang tidak kamu duga.
Yang dibangun spread syntax adalah shallow copy (copy yang cuma menduplikasi property level pertama, membiarkan object nested apa pun menunjuk ke hal yang sama). Value di level pertama jadi independen kalau mereka primitive, tapi saat yang di dalamnya adalah object atau array, informasi lokasinya — reference-nya — cuma di-copy apa adanya.
Saat kamu perlu bagian dalamnya dibangun ulang juga, pakai deep copy (copy yang membangun ulang semuanya, sampai ke value nested). Tulis structuredClone(order), dan tiap level nesting dibangun ulang sebagai object terpisah.
Itu function yang disediakan browser, jadi berfungsi langsung di console situs ini juga. Cuma tidak berfungsi pada object yang berisi function.
const order = {
orderId: "ORD-1342",
customer: { name: "Kenji Ross", city: "Denver" },
};
// Shallow copy: level pertama terpisah, bagian dalamnya masih menunjuk ke hal yang sama
const shallow = { ...order };
shallow.orderId = "ORD-9999";
console.log(order.orderId); // ORD-1342 (independen)
shallow.customer.city = "Boulder";
console.log(order.customer.city); // Boulder (aslinya ikut berubah)
console.log(order.customer === shallow.customer); // true
// Deep copy: bahkan bagian dalamnya jadi terpisah
const deep = structuredClone(order);
deep.customer.city = "Aurora";
console.log(order.customer.city); // Boulder (aslinya aman)
console.log(order.customer === deep.customer); // false
Menghentikan Tulis-Ulang — Object.freeze
Seperti yang sudah kamu lihat, array dan object bisa berubah tanpa sengaja cuma karena berbagi reference yang sama. Beberapa value, seperti default settings atau tax rate, butuh perlindungan yang beda dari const — kamu nggak mau itu ditulis ulang belakangan. const saja tidak menghentikan isinya ditulis ulang, jadi kamu perlu cara menandai object itu sendiri terlarang untuk diubah.
Tulis Object.freeze(settings), dan object itu berhenti menerima perubahan, penambahan, atau penghapusan pada property-nya. Coba assign, tambah, atau hapus sesuatu setelah membekukannya, dan itu melempar TypeError tepat di situ, menghentikan eksekusi.
Cek apakah sesuatu beku dengan Object.isFrozen(settings). Pembekuan cuma mencapai level pertama, jadi object nested perlu dibekukan terpisah.
const settings = { theme: "dark" };
// Bisa ditulis ulang sebelum dibekukan
settings.theme = "light";
console.log(settings.theme); // light
Object.freeze(settings);
console.log(Object.isFrozen(settings)); // true
// Meng-assign setelah dibekukan berhenti di baris itu
// settings.theme = "dark";
// TypeError: Cannot assign to read only property 'theme' of object '#<Object>'
// Pembekuan cuma mencapai level pertama — bagian dalamnya tidak berhenti
const nested = Object.freeze({ display: { theme: "dark" } });
nested.display.theme = "light";
console.log(nested.display.theme); // light
// Untuk mengubahnya, bangun object baru sebagai gantinya
const updated = { ...settings, theme: "dark" };
console.log(updated.theme); // dark
console.log(settings.theme); // light (aslinya aman)
Untuk Mengubahnya, Bangun Object Baru
Meng-assign, menambah, atau menghapus pada object beku melempar TypeError, dan tidak ada apa pun setelah baris itu yang berjalan. Untuk mengubah object beku, jangan tulis ulang — bangun yang baru sebagai gantinya, seperti { ...settings, theme: "light" }.
Cek Pemahaman
Jawab setiap pertanyaan satu per satu.
Soal 2Dengan const a = ["A"]; const b = ["A"];, apa yang dikembalikan a === b?
Soal 3Copy data dengan object nested memakai { ...order }. Apa yang terjadi pada object yang nested itu?