BAB 4: Operator
Aritmatika, perbandingan, logika, typeof, ternary, dan konversi tipe otomatis.
Di latihan akhir bab sebelumnya, kamu diminta memprediksi output dari typeof (1 + "2"). Jika kamu mencobanya, hasilnya adalah "string" — dan itu mungkin terasa aneh. Kenapa penjumlahan angka dengan string menghasilkan string? Jawabannya ada di cara operator JavaScript bekerja, terutama ketika menghadapi nilai bertipe berbeda.
Operator adalah simbol yang memberi tahu JavaScript untuk melakukan sesuatu terhadap satu atau lebih nilai. Kamu sudah menggunakan beberapa di bab sebelumnya tanpa disadari — typeof itu sendiri adalah operator. Di bab ini kita akan memetakan seluruh toolkit operator JavaScript secara sistematis, termasuk perilaku-perilaku yang tidak intuitif yang sering menjadi jebakan bagi pemula.
Operator Aritmatika
Operator aritmatika bekerja dengan angka, seperti yang kamu harapkan dari pelajaran matematika sekolah.
// aritmatika.js
console.log(10 + 4); // 14
console.log(10 - 4); // 6
console.log(10 * 4); // 40
console.log(10 / 4); // 2.5
console.log(10 % 4); // 2 -- sisa bagi
console.log(10 ** 4); // 10000 -- perpangkatan: 10 pangkat 4
Operator % (modulo) sering digunakan untuk mengecek apakah sebuah angka habis dibagi — nilai 0 berarti habis dibagi.
// aritmatika.js
let angka = 17;
console.log(angka % 2 === 0 ? "genap" : "ganjil"); // "ganjil"
console.log(16 % 2 === 0 ? "genap" : "ganjil"); // "genap"
Operator ** (eksponen) bersifat right-associative — artinya 2 ** 3 ** 2 dievaluasi sebagai 2 ** (3 ** 2) = 2 ** 9 = 512, bukan (2 ** 3) ** 2 = 64. Berbeda dari operator aritmatika lain yang dievaluasi dari kiri ke kanan.
Urutan Operasi
JavaScript mengikuti aturan matematika standar: perkalian dan pembagian dikerjakan lebih dulu sebelum penjumlahan dan pengurangan. Gunakan tanda kurung untuk memaksa urutan yang kamu inginkan.
console.log(2 + 3 * 4); // 14, bukan 20
console.log((2 + 3) * 4); // 20 -- kurung dikerjakan duluan
Increment dan Decrement
Dua operator singkat untuk menambah atau mengurangi nilai sebesar 1:
// aritmatika.js
let skor = 0;
skor++; // sama dengan: skor = skor + 1
console.log(skor); // 1
skor--; // sama dengan: skor = skor - 1
console.log(skor); // 0
Ada perbedaan halus antara bentuk prefix (++x) dan postfix (x++):
let a = 5;
let b = a++; // b mendapat nilai SEBELUM increment
console.log(a, b); // 6, 5
let c = 5;
let d = ++c; // d mendapat nilai SESUDAH increment
console.log(c, d); // 6, 6
Perbedaan ini paling relevan ketika ekspresi increment digunakan di dalam ekspresi yang lebih besar. Dalam kebanyakan kasus, skor++ dan ++skor ditulis sendiri (bukan sebagai bagian dari ekspresi lain) — dan keduanya identik hasilnya.
Operator Assignment
Operator = menyimpan nilai ke variabel. Tapi ada bentuk singkat yang menggabungkan operasi dengan assignment:
// assignment.js
let nilai = 100;
nilai += 10; // nilai = nilai + 10 → 110
nilai -= 5; // nilai = nilai - 5 → 105
nilai *= 2; // nilai = nilai * 2 → 210
nilai /= 3; // nilai = nilai / 3 → 70
nilai **= 2; // nilai = nilai ** 2 → 4900
nilai %= 100; // nilai = nilai % 100 → 0
console.log(nilai); // 0
Operator assignment selalu dikerjakan paling akhir dalam sebuah ekspresi. x = 3 + 4 pertama-tama mengevaluasi 3 + 4 menjadi 7, baru menyimpannya ke x.
Operator Perbandingan
Operator perbandingan menghasilkan nilai boolean: true atau false.
// perbandingan.js
console.log(5 > 3); // true
console.log(5 < 3); // false
console.log(5 >= 5); // true
console.log(5 <= 4); // false
== versus ===
Di sinilah JavaScript berbeda dari banyak bahasa lain. Ada dua operator kesamaan:
===(strict equality): membandingkan nilai dan tipe — tidak ada konversi otomatis==(loose equality): membandingkan nilai setelah melakukan konversi tipe otomatis
// perbandingan.js
console.log(5 === 5); // true
console.log(5 === "5"); // false -- tipe berbeda
console.log(5 == 5); // true
console.log(5 == "5"); // true -- "5" dikonversi ke 5
Perbedaan ini tampak sederhana, tapi aturan konversi == kompleks dan sering mengejutkan:
console.log("" == 0); // true -- string kosong jadi 0
console.log(false == 0); // true -- false jadi 0
console.log(null == undefined); // true -- pengecualian khusus
console.log(null == 0); // false -- null tidak dikonversi ke number
Baris terakhir itu perlu diperhatikan: null == 0 menghasilkan false, padahal null seolah "kosong" seperti 0. Aturan konversi == bukan aritmatika biasa — ada kasus-kasus spesial yang sulit dihafal. Gunakan === secara default untuk menghindari kejutan seperti ini.
Pasangan negatifnya: !== untuk strict tidak-sama, != untuk loose tidak-sama.
console.log(5 !== "5"); // true
console.log(5 != "5"); // false -- karena 5 == "5" adalah true
Praktis: gunakan === dan !== di seluruh kode. Cadangkan == hanya jika kamu punya alasan yang sangat spesifik.
Konversi Tipe Otomatis
JavaScript melakukan konversi tipe secara diam-diam ketika operasi melibatkan dua tipe yang berbeda. Ini disebut type coercion — dan ia adalah sumber kebingungan yang tiada habis bagi pemula.
Aturan terpenting yang perlu diingat: operator + dengan satu operand bertipe string akan menggabungkan string, bukan menjumlahkan angka.
// coercion.js
console.log(1 + "2"); // "12" -- angka dikonversi ke string
console.log("3" + 4); // "34" -- angka dikonversi ke string
console.log(1 + 2 + "3"); // "33" -- 1+2=3 dulu, lalu "3" + "3"
console.log("1" + 2 + 3); // "123" -- "1"+"2"="12", lalu "12"+"3"
Operator lain seperti -, *, / tidak bisa menggabungkan string — mereka mencoba mengonversi semua operand ke angka:
console.log("5" - 2); // 3 -- "5" dikonversi ke 5
console.log("5" * 2); // 10
console.log("abc" - 2); // NaN -- "abc" tidak bisa jadi angka
Jika kamu perlu mengonversi string ke number secara eksplisit, gunakan Number("5") atau +"5". Konversi eksplisit lebih mudah dibaca dan niatnya jelas.
Dari latihan di akhir Bab 3 — sekarang jelas mengapa typeof (true + 1) menghasilkan "number": true dikonversi ke 1, lalu 1 + 1 = 2. Dan typeof (null + 1) juga "number": null dikonversi ke 0, lalu 0 + 1 = 1.
Operator Logika
Operator logika bekerja dengan nilai boolean dan menghasilkan boolean — tapi ada keistimewaan penting yang perlu dipahami.
AND, OR, dan NOT
&&(AND):truehanya jika kedua sisitrue||(OR):truejika salah satu sisitrue!(NOT): membalik nilai boolean
// logika.js
console.log(true && true); // true
console.log(true && false); // false
console.log(false || true); // true
console.log(false || false); // false
console.log(!true); // false
console.log(!false); // true
Short-Circuit Evaluation
Ini adalah perilaku yang sangat berguna di JavaScript: ketika hasilnya sudah bisa dipastikan dari operand pertama, JavaScript tidak mengevaluasi operand kedua sama sekali.
Untuk &&: jika operand kiri adalah falsy, operand kanan tidak dievaluasi (hasilnya sudah pasti false).
Untuk ||: jika operand kiri adalah truthy, operand kanan tidak dievaluasi (hasilnya sudah pasti true).
Yang lebih menarik: && dan || mengembalikan nilai operand itu sendiri, bukan hanya true/false:
// logika.js
console.log(0 && "halo"); // 0 -- kiri falsy, dikembalikan langsung
console.log("ada" && "halo"); // "halo" -- kiri truthy, kanan yang dikembalikan
console.log(0 || "default"); // "default" -- kiri falsy, kanan yang dikembalikan
console.log("ada" || "default"); // "ada" -- kiri truthy, dikembalikan langsung
Perilaku ini sering dimanfaatkan untuk pola seperti ini:
// hanya panggil fungsi jika pengguna ada
let pengguna = { nama: "Budi" };
pengguna && console.log(pengguna.nama); // "Budi"
// nilai default jika variabel kosong
let namaPengguna = "";
let tampilan = namaPengguna || "Tamu";
console.log(tampilan); // "Tamu"
Nullish Coalescing (??)
Operator ?? mirip ||, tapi dengan satu perbedaan krusial: ia hanya menggunakan nilai kanan jika nilai kiri adalah null atau undefined — bukan semua nilai falsy.
// logika.js
let skor = 0;
console.log(skor || 10); // 10 -- karena 0 dianggap falsy oleh ||
console.log(skor ?? 10); // 0 -- karena 0 bukan null/undefined
let nama = "";
console.log(nama || "Anonim"); // "Anonim"
console.log(nama ?? "Anonim"); // "" -- string kosong bukan null/undefined
Gunakan ?? ketika nilai 0, false, atau string kosong adalah nilai yang valid dan tidak boleh diganti default. Gunakan || ketika semua nilai falsy harus diganti.
Operator typeof
typeof sudah kamu temui di Bab 3, tapi perlu ditegaskan: ia adalah operator unary, bukan fungsi — meski sering ditulis dengan kurung untuk kejelasan.
// typeof.js
console.log(typeof 42); // "number"
console.log(typeof "halo"); // "string"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof null); // "object" -- bug historis
console.log(typeof function(){}); // "function"
console.log(typeof {}); // "object"
console.log(typeof []); // "object" -- array juga object
Catatan penting: typeof tidak bisa membedakan antara array, plain object, dan null — ketiganya menghasilkan "object". Untuk mengecek array secara spesifik, gunakan Array.isArray().
Operator Ternary
Operator ternary adalah cara ringkas menulis kondisi sederhana dalam satu baris:
kondisi ? nilaiJikaTrue : nilaiJikaFalse
// ternary.js
let nilai = 75;
let status = nilai >= 60 ? "Lulus" : "Tidak Lulus";
console.log(status); // "Lulus"
let stok = 0;
let pesan = stok > 0 ? `Tersedia (${stok} unit)` : "Habis";
console.log(pesan); // "Habis"
Ternary cocok untuk assignment singkat. Hindari menumpuknya terlalu dalam — tiga level nesting ternary jauh lebih sulit dibaca dibanding if/else yang setara.
// ini sudah mulai susah dibaca
let kategori = nilai >= 90 ? "A" : nilai >= 75 ? "B" : nilai >= 60 ? "C" : "D";
Untuk kondisi seperti ini, if/else yang akan dibahas di Bab 7 jauh lebih jelas.
Latihan
Tiga soal berikut melatih kepekaan terhadap perilaku operator yang sudah dibahas:
-
Prediksi output dari kode berikut tanpa menjalankannya, lalu verifikasi di console:
let x = 10; console.log(x++ + 1); console.log(x); console.log(++x + 1); console.log(x);Apa perbedaan yang kamu amati antara
x++dan++xdalam konteks ini? -
JavaScript memiliki perilaku yang disebut falsy values. Prediksi mana dari ekspresi berikut yang menghasilkan nilai awal dan mana yang menghasilkan nilai default:
console.log(0 || "default"); console.log(0 ?? "default"); console.log(false || "default"); console.log(false ?? "default"); console.log("" || "default"); console.log("" ?? "default");Dari hasil ini, tulis dalam kalimatmu sendiri: kapan kamu akan memilih
??dibanding||? -
Buat sebuah program yang menghitung diskon untuk belanja online. Harga asli disimpan dalam variabel
hargaAsli. Program memberikan diskon 20% jika harga di atas 500.000, dan diskon 10% jika harga antara 200.000 dan 500.000. Jika di bawah 200.000, tidak ada diskon. Gunakan operator ternary dan aritmatika untuk menghitunghargaAkhir, lalu tampilkan hasilnya.
Memahami operator berarti memahami bahasa dasarnya — ekspresi apa pun yang kamu tulis nantinya adalah kombinasi dari nilai dan operator. Tapi ekspresi itu sendiri hanyalah satu jenis konstruksi dalam JavaScript. Di bab berikutnya, kita akan membedah perbedaan antara ekspresi dan statement — dua konsep yang terlihat teknis tapi sangat mempengaruhi cara kamu membaca dan menulis kode JavaScript.