Data yang masuk dari formulir web dan dari parameter URL selalu berupa string. Jadi ketika pengguna mengisi usia 18, program menerima teks "18" — dan teks itu tidak identik dengan angka 18. Jika kita memeriksa usia === 18 dan hasilnya selalu false, bug-nya bukan pada nilai, melainkan pada tipe. Di sinilah dua operator kesetaraan JavaScript memainkan peran berbeda, dan salah memilihnya menjadi salah satu sumber bug paling umum bagi pemula.

Chapter penutup section ini membedakan === (strict equality) dan == (loose equality), membuktikan perilaku keduanya pada kasus-kasus paling penting, dan menjelaskan mesin di balik layar: type coercion, konversi tipe yang terjadi tanpa suara.

Dua Operator Kesamaan #

Operator === menanyakan “apakah nilai dan tipenya sama-sama identik?”. Operator == menanyakan versi longgar: “apakah setelah dikonversi ke tipe yang sama, nilainya sama?”. Perbedaan satu tanda sama dengan itu berdampak besar:

EkspresiHasilPenjelasan
5 == 5trueNilai dan tipe sama
5 === 5trueSama seperti di atas
5 == "5"true"5" dikonversi menjadi 5 sebelum dibandingkan
5 === "5"falseTipe berbeda: number versus string
null == undefinedtruePasangan khusus yang setara pada ==
null === undefinedfalseTipe berbeda: null versus undefined
0 == falsetruefalse dikonversi menjadi 0
0 === falsefalseTipe berbeda: number versus boolean
NaN === NaNfalseNaN tidak sama dengan nilai apa pun

Baris terakhir patut digarisbawahi: NaN bahkan tidak sama dengan dirinya sendiri. Karena itu nilai === NaN tidak akan pernah true, dan pemeriksaan NaN harus memakai fungsi khusus Number.isNaN() — sudah kita gunakan di chapter Arithmetic Operators.

Koersi: Konversi yang Terjadi Senyap #

Mekanisme == bisa dirangkum: engine melihat kedua tipe; bila berbeda, engine mengonversinya mengikuti aturan bawaan spesifikasi, lalu membandingkan hasilnya. Aturan-aturan itu terasa wajar pada kasus sederhana ("5" menjadi angka 5), tetapi makin sulit ditebak pada kombinasi lain:

js
console.log("" == 0);
console.log("0" == 0);
console.log("0" == false);
console.log(true == 1);

Output yang Dihasilkan:

text
true
true
true
true

String kosong "", string "0", boolean false, dan angka 0 — empat nilai yang secara makna berbeda-beda — semuanya dianggap sama oleh ==. Ada satu pengecualian yang terasa rapi di tengah aturan longgar ini: null hanya setara dengan undefined (dan dirinya sendiri). Pemeriksaan null == 0 menghasilkan false, begitu pula undefined == 0. Konversi senyap semacam ini berlaku bukan hanya pada ==; operator perbandingan < dan > dari chapter Comparison Operators pun melakukan koersi ketika kedua sisi bertipe beda — alasan tambahan untuk selalu menyamakan tipe sebelum membandingkan.

Menguji Perilaku Secara Nyata #

Berkas berikut merangkum semua kasus penting dari tabel di atas. Jalankan dan cocokkan tiap baris dengan dugaan kita:

// uji-kesamaan.js
// Membuktikan perbedaan == dan === serta perilaku NaN.

console.log(5 == 5);
console.log(5 === 5);

// == melakukan konversi tipe terlebih dahulu.
console.log(5 == "5");
console.log(5 === "5");

// null dan undefined saling setara pada ==, tetapi tidak pada ===.
console.log(null == undefined);
console.log(null === undefined);

// false dikonversi menjadi 0 sebelum dibandingkan.
console.log(0 == false);
console.log(0 === false);

// NaN tidak sama dengan nilai apa pun, termasuk dirinya sendiri.
console.log(NaN === NaN);
console.log(Number.isNaN(NaN));

Output yang Dihasilkan:

text
true
true
true
false
true
false
true
false
false
true

Mari kita telaah baris-baris pentingnya:

  1. Baris 4–5 (5 == 5 dan 5 === 5): tanpa perbedaan tipe, kedua operator sepakat — keduanya true.
  2. Baris 8 (console.log(5 == "5");): == mengonversi "5" menjadi angka 5, lalu membandingkannya; hasilnya true.
  3. Baris 9 (console.log(5 === "5");): === berhenti di perbedaan tipe tanpa mencoba mengonversi; hasilnya false. Dua baris berdampingan ini adalah inti chapter.
  4. Baris 12–13 (null == undefined dan null === undefined): == menganggap keduanya setara (keduanya penanda “tidak ada nilai”), sedangkan === tetap melihat tipe yang berbeda dan menghasilkan false.
  5. Baris 16–17 (0 == false dan 0 === false): false dikonversi menjadi 0 oleh ==; === menolaknya karena boolean dan number adalah tipe berbeda.
  6. Baris 20 (console.log(NaN === NaN);): hasilnya false — bukti langsung bahwa NaN tidak bisa dibandingkan dengan dirinya sendiri, apalagi dengan nilai lain.
  7. Baris 21 (console.log(Number.isNaN(NaN));): fungsi Number.isNaN() menghasilkan true hanya untuk NaN — satu-satunya cara andal mendeteksinya.

Kebalikannya: !== dan != #

Kedua operator kesetaraan punya pasangan negasi: !== (strict inequality) dan != (loose inequality). Kebalikannya konsisten — apa yang dikatakan sama oleh ==, dikatakan berbeda oleh !=, begitu pula pasangan === dan !==:

js
console.log(5 !== "5");
console.log(5 != "5");

Output yang Dihasilkan:

text
true
false

Baris pertama memakai !==: karena 5 dan "5" berbeda tipe, !== menyatakannya berbeda dan menghasilkan true. Baris kedua memakai !=: konversi tipe menyamakan 5 dan "5" lebih dulu, sehingga hasilnya false. Aturan pemilihannya sama persis dengan kesetaraan — pilih versi strict agar konversi tipe tidak terjadi senyap.

Aturan Praktis: Selalu === #

Aturan yang berlaku di hampir seluruh kode modern: gunakan === dan !== untuk semua pemeriksaan kesamaan. Operator === membuat konversi tipe jadi masalah yang terlihat, bukan tersembunyi — bila data dari formulir datang sebagai string "18", pemeriksaan usia === 18 akan gagal dengan jelas, memberi kita kesempatan mengonversi nilainya secara eksplisit (dengan Number(), seperti di section Values dan Types) alih-alih mengandalkan koersi senyap.

Ada satu pengecualian kecil yang diakui luas: pola nilai == null untuk memeriksa “nilai ini null atau undefined sekaligus” memanfaatkan pasangan khusus di tabel. Pola itu sah, tetapi menulis nilai === null || nilai === undefined jauh lebih eksplisit — dan konsisten dengan aturan utamanya. Dengan aturan === ini, section Operators tuntas: kita kini bisa menghitung, membandingkan, menggabungkan kondisi, memberi nilai cadangan, mengakses data bertingkat, memilih nilai dengan ternary, dan membaca urutan evaluasi dengan benar.

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

uji-kesamaan.js

Unduh berkas
javascript
// uji-kesamaan.js
// Membuktikan perbedaan == dan === serta perilaku NaN.

console.log(5 == 5);
console.log(5 === 5);

// == melakukan konversi tipe terlebih dahulu.
console.log(5 == "5");
console.log(5 === "5");

// null dan undefined saling setara pada ==, tetapi tidak pada ===.
console.log(null == undefined);
console.log(null === undefined);

// false dikonversi menjadi 0 sebelum dibandingkan.
console.log(0 == false);
console.log(0 === false);

// NaN tidak sama dengan nilai apa pun, termasuk dirinya sendiri.
console.log(NaN === NaN);
console.log(Number.isNaN(NaN));