Krisis Identitas JS: Keyword `this`
Jika kamu membaca kode programmer asing, kamu pasti sering melihat kata sakti this.nama atau
this.umur. Namun ini adalah fitur paling rentan salah kaprah di seluruh penjuru JavaScript!
Di bahasa kuno seperti Java/C++, this selalu merujuk pada "Kelas Tempat Di Mana Aku Lahir".
Tapi di JavaScript, Keyword `this` itu sangat plin-plan. Ia tidak peduli di mana ia LAHIR,
ia hanya peduli pada SIAPA YANG SEDANG MEMANGGILNYA SAAT INI (Pada detik kode dieksekusi).
Mari kita pelajari kelabilan this dan bagaimana cara kita mengurung paksa identitasnya dengan
borgol call, apply, dan bind!
🎭 1. Bukti Plin-Plan Identitas `this`
Mari kita buktikan hukum utama: *"Nilai dari this ditentukan oleh Objek apa yang berada di
sebelah kiri Tanda Titik saat fungsi tersebut dipanggil"*.
const userA = {
nama: "Andi",
sapa: function() {
// this merujuk pada objek "Pemanggil" saat dipenghujung jalan
console.log(`Halo, saya ${this.nama}!`);
}
};
const userB = {
nama: "Budi"
};
✅ Kasus Normal:
userA.sapa();
// Ouput: "Halo, saya Andi!" (Krn "userA" yg memanggil di sebalah kiri titik)
❌ Krisis Identitas:
const fungsiNyasar = userA.sapa; // Memutus ikatan fungsi, ditarik ke udara!
fungsiNyasar(); // Memanggil tanpa "." di sebelah kiri
// Output: "Halo, saya undefined!" 😱 (Krna di alam bebas, 'this' menjadi Global Window)
🔄 Pencurian Identitas:
userB.pinjamSuara = userA.sapa; // Budi mencuri fungsi Andi
userB.pinjamSuara();
// Output: "Halo, saya Budi!" (Padahal kodenya ditulis di dalam objek Andi 🤯)
💡
Aturan Emas: Jika kamu memanggil sebuah fungsi dengan gaya telanjang bulat alias
sendirian: fungsiNyasar(), maka this di dalamnya otomatis terlempar pulang ke
wujud Super Semesta (Objek window di Browser, atau menolak jalan dengan status
undefined jika Mode Ketat / Strict Mode menyala).
🏹 2. Pengecualian Emas: Arrow Function
Masalah kelabilan this ini begitu kacau sampai membuat banyak programmer frustasi. Karena itulah
ES6 merilis Arrow Function =>. Arrow function secara genetik TIDAK memiliki
this miliknya sendiri! Ia adalah Anak berbakti yang mengadopsi identitas `this` murni dari
lingkungan tempat ia dilahirkan, persis seperti Java/C++.
const mobil = {
brand: "Ferrari",
nyalakanMesin: function() {
// 'this' normal! Ia merujuk pada objek Mobil saat dipanggil 'mobil.nyalakanMesin()'
console.log(`Menyalakan ${this.brand}...`);
setTimeout(() => {
// AJAIB! Kalau pakai function() biasa, 'this' akan jadi Window krn setTimeout berjalan mandiri tanpa "Tanda Titik".
// Tapi karena Arrow =>, 'this' akan Mewarisi Bapaknya (Objek Mobil)
console.log(`${this.brand} sudah menderu! Vroooom!`);
}, 2000);
}
};
mobil.nyalakanMesin();
// Detik 0: "Menyalakan Ferrari..."
// Detik 2: "Ferrari sudah menderu! Vroooom!"
🔗 3. Metode Pemaksaan: Call, Apply, Bind
Lalu bagaimana jika kita terlanjur memiliki fungsi lama (bukan Arrow), tapi kita ingin MEMAKSA fungsi tersebut berganti identitas / meminjam Objek lain secara sengaja? JavaScript (mulai ES5) mempersenjatai kita dengan 3 Metode Pembajakan:
.call()
"Telepon Sekarang"
Menjalankan fungsi SAAT INI JUGA, dengan identitas `this` yang dipaksa, diikuti dengan argumen biasa yang dipisahkan oleh tanda baca Koma (`,`).
sapa.call(objBudi, "Pagi", 100);
.apply()
"Apply Segepok"
Identik persis 100% dengan `call()`. Bedanya hanya satu: alih-alih melempar argumen satu per satu pakai Koma, fungsi ini menelan sebuah rentetan keranjang **Array `[ ]`**.
sapa.apply(objBudi, ["Pagi", 100]);
.bind()
"Borgol & Kemas"
(Paling Populer di React!). Ia **TIDAK menjalankan** fungsinya sekarang. Melainkan memborgol identitas barunya permanen, lalu mencetaknya **sebagai fungsi utuh baru** untuk dipanggil kelak kapan-kapan!
const fnBaru = sapa.bind(objBudi);
// ... Nanti dipanggil:
fnBaru("Pagi");
🎮 Studi Kasus Interaktif: Pembajakan Data Rumah Sakit
Ubah metode di bawah ini dan lihat bagaimana Klinik Desa menumpang fungsi Cetak dari RS Pusat!
rsUmum.cetakTagihan.call(klinikDesa, 'Gigi', 50000)
▶ [Klinik Makmur] Pasien poli Gigi dikenakan biaya Rp 50000.
rsUmum.cetakTagihan.apply(klinikDesa, ['Mata', 150000])
▶ [Klinik Makmur] Pasien poli Mata dikenakan biaya Rp 150000.
const mesinBaru = rsUmum.cetakTagihan.bind(klinikDesa)
-- Fungsi mesinBaru sudah diciptakan di Memory! --
mesinBaru('Jantung', 9000000)
▶ [Klinik Makmur] Pasien poli Jantung dikenakan biaya Rp 9000000.