Koersi tipe

Konversi tipe otomatis, perbandingan == vs ===, dan nilai truthy/falsy.

Daftar isi

JavaScript mengubah tipe nilai secara otomatis ketika operasi menuntut tipe yang berbeda, dan proses otomatis ini disebut koersi, yakni konversi tipe yang dilakukan bahasa di belakang layar. Topik ini membahas perbandingan == versus ===, nilai truthy dan falsy, yaitu nilai yang dianggap benar atau salah oleh bahasa, serta beberapa kejutan klasik beserta mekanisme di baliknya. Koersi membuat kode menjadi ringkas, tetapi juga menghasilkan keluaran yang tampak mustahil bagi yang belum mengenal aturannya. Setelah mekanismenya dipahami, keluaran semacam itu menjadi dapat diprediksi.

== dan ===#

Operator == membandingkan dua nilai setelah mengonversinya ke tipe yang sama, sedangkan === membandingkan nilai sekaligus tipenya tanpa konversi apa pun. Karena itu === disebut perbandingan ketat (strict equality). Perbedaannya terlihat pada beberapa kasus berikut.

js Contoh: == mengonversi, === tidak
console.log(1 == "1");
console.log(1 === "1");
console.log(0 == false);
console.log(0 === false);
console.log(null == undefined);
console.log(null === undefined);
text Keluaran
true
false
true
false
true
false

Empat baris pertama menunjukkan == yang memaksa konversi sebelum membandingkan, sehingga angka 1 dan string “1” dianggap sama, sedangkan === menolaknya karena tipenya berbeda. Dua baris terakhir adalah pengecualian yang dirancang khusus, yaitu null dan undefined yang dianggap sama oleh == namun berbeda oleh ===. Aturan praktis yang lazim di seluruh ekosistem adalah selalu memakai ===, kecuali satu kasus, yaitu membandingkan dengan null sekaligus undefined dalam satu langkah. Contoh berikut memperlihatkan pola pengecualian itu.

js Contoh: pengecualian == dengan null
const input = null;
console.log(input === null || input === undefined);
console.log(input == null);
text Keluaran
true
true

Kedua baris keluaran bernilai sama, dan input == null menangkap dua nilai kosong itu sekaligus dalam satu perbandingan. Pengecualian ini satu-satunya yang dianjurkan, sedangkan untuk semua perbandingan lain === adalah pilihan default yang menghindarkan kode dari konversi tersembunyi. Banyak gaya penulisan JavaScript bahkan melarang == selain untuk kasus di atas. Disiplin kecil ini menghilangkan satu sumber kejutan yang besar.

Truthy dan falsy#

Setiap nilai di JavaScript akhirnya berubah menjadi true atau false ketika konteks menuntut nilai boolean, misalnya kondisi if. Nilai yang berubah menjadi false disebut falsy, sedangkan sisanya disebut truthy. Daftar falsy pendek dan terdiri atas enam nilai, yaitu false, 0, string kosong "", null, undefined, dan NaN. Semua nilai lain, termasuk string “0”, array kosong, dan object kosong, adalah truthy.

js Contoh: enam nilai falsy dan tiga nilai truthy
console.log(Boolean(false));
console.log(Boolean(0));
console.log(Boolean(""));
console.log(Boolean(null));
console.log(Boolean(undefined));
console.log(Boolean(NaN));
console.log(Boolean("hai"));
console.log(Boolean(42));
console.log(Boolean([]));
text Keluaran
false
false
false
false
false
false
true
true
true

Fungsi Boolean() dipakai di atas sebagai alat peraga, padahal dalam kode nyata konversi ini terjadi sendiri di dalam kondisi if atau di sisi kiri operator logika. Tiga baris terakhir sering mengejutkan pembaca baru. String “0” tetap truthy karena berisi karakter, dan array kosong juga tetap truthy. Menghafal enam nilai falsy jauh lebih murah daripada mencoba mengingat seluruh nilai yang truthy. Daftar ini dipakai lagi ketika membahas percabangan pada modul alur kendali.

Kejutan klasik dan mekanismenya#

Kejutan koersi yang paling terkenal berputar pada operator +, karena operator ini punya dua peran, yaitu penjumlahan angka dan penggabungan string. Ketika salah satu sisi + adalah string, JavaScript memilih peran penggabungan dan mengonversi sisi lainnya menjadi string. Operator aritmetika lain tidak punya pilihan itu, sehingga kedua sisinya dikonversi menjadi number. Perbedaan keputusan inilah yang menghasilkan keluaran berikut.

js Contoh: tanda plus berbeda dari operator lain
console.log("1" + 1);
console.log("1" - 1);
console.log("5" * "2");
console.log(1 + 2 + "3");
text Keluaran
11
0
10
33

Baris pertama menghasilkan string “11” karena angka 1 dikonversi menjadi string lalu ditempel ke belakang “1”. Baris kedua menghasilkan angka 0, karena tanda minus memaksa “1” dikonversi menjadi number. Baris ketiga menunjukkan perkalian yang juga mengonversi kedua string menjadi angka. Baris keempat menunjukkan evaluasi dari kiri, yaitu 1 + 2 dikerjakan lebih dahulu sebagai penjumlahan angka menjadi 3, lalu 3 + “3” berpindah peran menjadi penggabungan dan menghasilkan “33”. Mekanisme yang sama bekerja pada array, karena array dikonversi menjadi string dengan menggabungkan elemen-elemennya memakai koma.

js Contoh: array dan object dalam penggabungan
console.log("[] + {} :", [] + {});
console.log("[] + [] :", JSON.stringify([] + []));
console.log("[1, 2] + [3] :", [1, 2] + [3]);
text Keluaran
[] + {} : [object Object]
[] + [] : ""
[1, 2] + [3] : 1,23

Array kosong dikonversi menjadi string kosong, sehingga [] + {} sebenarnya adalah "" + “[object Object]”, dan object biasa memang direpresentasikan sebagai teks “[object Object]”. Baris terakhir menggabungkan “1,2” dengan “3” menjadi “1,23”, bukan penjumlahan array apa pun. Contoh semacam ini jarang ditulis dengan sengaja, tetapi sering muncul sebagai bug ketika satu operan ternyata bukan angka. Mengenali mekanismenya mempercepat pelacakan, karena pertanyaannya selalu sama, yaitu peran apa yang dipilih operator + pada setiap langkah.

Konversi yang memang diinginkan#

Koersi otomatis berbeda dari konversi yang sengaja dipanggil. Fungsi Number() mengubah nilai menjadi angka dan menghasilkan NaN bila isinya tidak dapat diperhitungkan, sedangkan String() dan Boolean() mengubah nilai ke string atau boolean secara eksplisit. Konversi eksplisit biasanya ditempatkan pada batas masukan, misalnya sebelum isi kotak pencarian dihitung, agar sisanya berjalan dengan tipe yang sudah pasti. Cara ini jauh lebih mudah ditebak daripada membiarkan operator yang memutuskan.

js Contoh: konversi eksplisit
console.log(Number("42"));
console.log(Number("42 kg"));
console.log(String(42));
console.log(Boolean("0"));
text Keluaran
42
NaN
42
true

Baris kedua memperlihatkan NaN yang khas, karena string “42 kg” memang tidak dapat dikonversi penuh menjadi angka. Konversi yang gagal tidak menghentikan program, melainkan menyebar sebagai NaN dan ikut meracuni setiap perhitungan berikutnya. Memeriksa hasil konversi dengan Number.isNaN() sebelum dipakai adalah kebiasaan yang menghemat banyak waktu pelacakan error. Gabungan konversi eksplisit dan perbandingan ketat menutup hampir seluruh celah kejutan koersi pada kode sehari-hari.

Ringkasan#

  • Koersi adalah konversi tipe otomatis yang dilakukan JavaScript ketika operasi menuntut tipe tertentu.
  • === membandingkan nilai sekaligus tipe tanpa konversi dan menjadi pilihan default, kecuali membandingkan dengan null sekaligus undefined.
  • Nilai falsy hanya enam, yaitu false, 0, string kosong, null, undefined, dan NaN, sedangkan sisanya truthy.
  • Operator + menggabungkan string bila salah satu sisinya string, sedangkan operator lain mengonversi seluruh sisinya menjadi number.

Referensi#