Nilai, Tipe, dan Operator

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.

JavaScriptJAVASCRIPT
// 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.

JavaScriptJAVASCRIPT
// 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.

JavaScriptJAVASCRIPT
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:

JavaScriptJAVASCRIPT
// 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++):

JavaScriptJAVASCRIPT
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:

JavaScriptJAVASCRIPT
// 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.

JavaScriptJAVASCRIPT
// 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
JavaScriptJAVASCRIPT
// 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:

JavaScriptJAVASCRIPT
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.

JavaScriptJAVASCRIPT
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.

JavaScriptJAVASCRIPT
// 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:

JavaScriptJAVASCRIPT
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): true hanya jika kedua sisi true
  • || (OR): true jika salah satu sisi true
  • ! (NOT): membalik nilai boolean
JavaScriptJAVASCRIPT
// 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:

JavaScriptJAVASCRIPT
// 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:

JavaScriptJAVASCRIPT
// 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 undefinedbukan semua nilai falsy.

JavaScriptJAVASCRIPT
// 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.

JavaScriptJAVASCRIPT
// 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:

JavaScriptJAVASCRIPT
kondisi ? nilaiJikaTrue : nilaiJikaFalse
JavaScriptJAVASCRIPT
// 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.

JavaScriptJAVASCRIPT
// 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:

  1. Prediksi output dari kode berikut tanpa menjalankannya, lalu verifikasi di console:

    JavaScriptJAVASCRIPT
    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 ++x dalam konteks ini?

  2. JavaScript memiliki perilaku yang disebut falsy values. Prediksi mana dari ekspresi berikut yang menghasilkan nilai awal dan mana yang menghasilkan nilai default:

    JavaScriptJAVASCRIPT
    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 ||?

  3. 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 menghitung hargaAkhir, 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.

Referensi

  1. 1 Expressions and Operators - JavaScript Guide | MDN Web Docs
  2. 2 Equality comparisons and sameness - JavaScript Guide | MDN Web Docs
  3. 3 Nullish coalescing operator (??) - JavaScript Reference | MDN Web Docs
  4. 4 Operator precedence - JavaScript Reference | MDN Web Docs