Soal 1Di constructor sebuah class yang punya status = "Baru";, apa yang terjadi kalau kamu membaca this.status?
constructor dan Class Field — Menentukan Value Awal
Constructor dan class field menentukan value awal instance. Membahas penyimpanan argument, urutan pengisian field, value bawaan, dan penolakan value yang tidak valid.
Tiket layanan pelanggan punya value yang berbeda di setiap tiket, seperti judulnya, dan value awal yang sama untuk semua tiket, seperti status "Baru". Kalau class-nya ditulis asal-asalan, value yang dikosongkan atau value yang tidak valid ikut tersimpan di instance.
Artikel ini membahas constructor, yang menerima value saat instance dibuat, dan class field, yang mendeklarasikan value awal yang sudah pasti.
Merapikan Argument Sebelum Disimpan — Body constructor
Judul tiket yang dikirim lewat formulir layanan pelanggan kadang punya spasi berlebih di awal atau di akhir. Kalau string tampilan seperti "Budi: Gagal login" baru disusun setelah instance dibuat, setiap halaman yang menampilkannya butuh kode trim dan penyusun string-nya sendiri.
Di body constructor, argument tidak harus disimpan apa adanya. Kamu bisa menyimpan versi yang sudah dirapikan, seperti this.title = title.trim(), atau value yang disusun dari beberapa argument. Setiap halaman tinggal membaca property instance dan langsung mendapat value yang sudah rapi.
class Ticket {
constructor(title, customerName) {
// Rapikan argument sebelum menyimpannya di this
this.title = title.trim();
this.customerName = customerName;
// Susun value tampilan dari this, setelah dirapikan
this.label = `${this.customerName}: ${this.title}`;
// Kalau ditulis `${customerName}: ${title}`, spasi di judul ikut terbawa
}
}
// Berikan judul yang punya spasi di awal dan akhir
const ticket = new Ticket(" Gagal login ", "Budi");
console.log(ticket.title); // Gagal login
console.log(ticket.label); // Budi: Gagal login
Baris atas membaca argument title, sedangkan baris bawah membaca this.title setelah trim. Kalau baris label dipindah ke awal constructor, this.title maupun this.customerName belum di-assign, jadi label menjadi undefined: undefined.
Menuliskan Value Awal yang Sudah Pasti — Class Field
Setiap tiket yang masuk dimulai dengan status "Baru" dan nol komentar. Kalau value awal seperti ini, yang tidak ada hubungannya dengan argument, ditulis di constructor sebagai this.status = "Baru";, baris-baris itu bercampur dengan baris yang menyimpan argument, dan kamu harus membaca seluruh body untuk tahu apa saja yang dimiliki instance.
Class field (property yang dideklarasikan di dalam kurung kurawal class tapi di luar constructor dan method, lalu ditambahkan ke instance setiap kali new dipanggil) cukup ditulis sebagai nama dan value awal, tanpa this, seperti status = "Baru";. Untuk membacanya dari body constructor atau dari method, tulis this.status, sama seperti property lainnya.
class Ticket {
// Value awal yang tidak bergantung pada argument ditulis sebagai field
status = "Baru";
comments = [];
constructor(title) {
this.title = title;
this.summary = `[${this.status}] ${title}`; // Value field sudah bisa dibaca di sini
}
}
const first = new Ticket("Gagal login");
const second = new Ticket("Invoice belum diterima");
console.log(first.summary); // [Baru] Gagal login
// comments adalah array terpisah yang dibuat setiap kali new dipanggil
first.comments.push("Pelanggan diminta me-restart perangkat");
console.log(first.comments.length); // 1
console.log(second.comments.length); // 0
new, field ditambahkan lebih dulu, baru kemudian body constructor berjalan. Body sudah bisa membaca value field.Langkah ① diulang setiap kali new dipanggil, jadi comments = [] menjadi array terpisah untuk setiap instance, dan komentar yang ditambahkan ke first tidak ikut masuk ke second. Karena itulah second.comments.length tetap 0.
Menulis this. di Field Melempar SyntaxError
Kalau kamu menulis this.status = "Baru"; di tempat field (di luar constructor), muncul SyntaxError: Unexpected token '.' dan tidak ada satu baris pun yang berjalan. Menambahkan let atau const juga melempar SyntaxError. Field cukup berisi nama dan value awal.
Menentukan Value Saat Argument Dikosongkan — Default Parameter
Sebagian besar tiket berprioritas "Normal", dan kamu hanya ingin memberikan "Mendesak" kalau ada hal yang perlu segera ditangani. Kalau kamu menulis field priority = "Normal"; lalu juga menambahkan this.priority = priority; di body, tiket yang dibuat tanpa prioritas tidak akan bernilai "Normal".
Default parameter (cara menentukan value yang dipakai kalau argument tidak dioper), yang sudah kamu lihat di artikel tentang default parameter dan rest parameter, juga bisa dipakai di constructor: tulis priority = "Normal" di daftar parameter. Argument yang dikosongkan atau bernilai undefined diganti dengan value bawaan sebelum body berjalan, jadi this.priority = priority menerima "Normal".
// Value bawaan di field, ditambah assign argument di body
class DraftTicket {
priority = "Normal";
constructor(title, priority) {
this.title = title;
this.priority = priority; // priority di kanan adalah argument (undefined kalau dikosongkan)
}
}
console.log(new DraftTicket("Gagal login").priority); // undefined
// Untuk value yang bisa diubah lewat argument, tulis value bawaan di default parameter
class Ticket {
constructor(title, priority = "Normal") {
this.title = title;
this.priority = priority;
}
}
console.log(new Ticket("Gagal login").priority); // Normal
console.log(new Ticket("Invoice belum diterima", "Mendesak").priority); // Mendesak
undefined dari argument. Yang tersisa di akhir adalah value yang di-assign di body.Tulis value yang bisa diubah lewat argument di default parameter, dan value yang tidak bergantung pada argument di field. Untuk value yang bergantung pada kondisi argument, seperti ongkos kirim di Latihan 2, pakai if di body untuk mengubah value awal field. Tabel di bawah menunjukkan value yang tersisa di priority untuk setiap cara, dengan dan tanpa "Mendesak", termasuk cara yang tidak meng-assign-nya di body.
| Cara | Hanya judul | Dengan "Mendesak" |
|---|---|---|
| Hanya field (tanpa assign di body) | Normal | Normal (diabaikan) |
| Field + this.priority = priority | undefined | Mendesak |
| Default parameter priority = "Normal" | Normal | Mendesak |
Menolak Value yang Tidak Valid — throw di constructor
Kalau sampai ada tiket dengan judul kosong, atau dengan prioritas di luar value yang sudah disepakati seperti "Tinggi", daftar tiket menampilkan baris kosong, dan tiket itu tidak ikut terhitung saat kamu menghitung tiket "Mendesak". Walaupun kamu menulis function terpisah untuk memeriksa tiket setelah dibuat, halaman yang lupa memanggilnya tetap memakai instance yang tidak valid.
Untuk validasi saat pembuatan (memeriksa, pada saat instance dibuat, bahwa value yang diterima memenuhi aturan), tulis if di dalam constructor dan lempar exception dengan throw new Error(...) kalau value-nya tidak lolos. Begitu exception dilempar, ekspresi new tidak mengembalikan instance.
class Ticket {
constructor(title, priority = "Normal") {
// Tolak value yang tidak valid dengan exception sebelum masuk ke this
if (title.trim() === "") {
throw new Error("Judul kosong");
}
if (priority !== "Normal" && priority !== "Mendesak") {
throw new Error(`Prioritas harus Normal atau Mendesak: ${priority}`);
}
this.title = title.trim();
this.priority = priority;
}
}
try {
const ticket = new Ticket("Gagal login", "Tinggi");
console.log(ticket.title); // Baris ini tidak pernah berjalan
} catch (error) {
console.log(error.message); // Prioritas harus Normal atau Mendesak: Tinggi
}
const ticket = new Ticket(...)— sisi kanan melempar exception, jaditickettidak berisi apa punconsole.log(ticket.title)— tidak pernah berjalan
- Cek judul — tidak kosong, jadi lolos
- Cek prioritas — isinya
"Tinggi", jadithrowdijalankan this.title = ...— mulai dari sini ke bawah tidak berjalan
error.message— "Prioritas harus Normal atau Mendesak: Tinggi"
new, melewati sisa try, lalu sampai di catch. Instance yang tidak valid tidak pernah masuk ke variabel mana pun.Dengan pengecekan di constructor, tidak ada tiket tidak valid yang bisa lolos, di mana pun new Ticket(...) dipanggil. Kalau value yang ditolak kamu sertakan di pesan exception, sisi catch juga bisa menampilkan value mana yang tidak valid.
Assignment Setelah Instance Dibuat Tidak Diperiksa
Pengecekan di constructor hanya berjalan saat new. Kalau kamu meng-assign ticket.priority = "Tinggi"; setelah tiket dibuat, tidak ada error, dan value-nya langsung tertimpa. Cara memeriksa value di setiap assignment dibahas di artikel tentang getter dan setter.
Cek Pemahaman
Jawab setiap pertanyaan satu per satu.
Soal 2Sebuah class hanya punya field priority = "Normal"; dan tidak meng-assign-nya di body. Apa yang terjadi kalau kamu memberikan "Mendesak"?
Soal 3Di dalam try, constructor melempar exception saat const ticket = new Ticket(""). Apa yang terjadi?