Dari masa sekolah kita sudah tahu: 2 + 3 * 4 bernilai 14, bukan 20, karena perkalian dihitung sebelum penjumlahan. Engine JavaScript memegang aturan urutan yang sama — ditambah banyak aturan lain untuk operator non-matematika. Kesalahan menebak urutan ini berbahaya secara senyap: program tetap berjalan, tidak ada pesan error, tetapi hasilnya meleset dari maksud kita.
Chapter ini merangkum urutan prioritas (operator precedence) utama, membuktikannya dengan ekspresi campur, membahas arah evaluasi untuk operator setara, dan menutup dengan satu kasus khusus yang memang ditolak engine: memadukan ?? dengan || atau && tanpa tanda kurung.
Tabel Urutan Prioritas #
Daftar berikut disusun dari yang paling diutamakan (dihitung lebih dulu) hingga yang paling akhir:
| Urutan | Operator | Contoh |
|---|---|---|
| 1 | () tanda kurung | (2 + 3) * 4 |
| 2 | ** pangkat | 2 ** 10 |
| 3 | Unary: -x, !x | -angka, !aktif |
| 4 | * / % | total % 3 |
| 5 | + - | a + b |
| 6 | < <= > >= | nilai >= batas |
| 7 | == === != !== | nilai === 1 |
| 8 | && | lulus && aktif |
| 9 | || | kupon || poin |
| 10 | ?? | input ?? 0 |
| 11 | ?: ternary | stok > 0 ? "ada" : "habis" |
| 12 | = += -= dst. | stok += 5 |
Cara membacanya: operator pada urutan lebih atas mengikat operand-nya lebih kuat. Baris 6–7 memuat dua kelompok perbandingan; keduanya berada di bawah aritmatika (sehingga 3 + 4 > 5 dibaca (3 + 4) > 5) dan di atas operator logika (sehingga hasil perbandingan langsung menjadi operand &&).
Membuktikan Urutan dengan Ekspresi Campur #
Berkas berikut menguji enam ekspresi yang masing-masing menyentuh bagian tabel berbeda. Tebak dulu hasilnya, lalu bandingkan dengan keluaran:
// urutan-hitung.js
// Membuktikan urutan evaluasi operator dengan ekspresi campur.
// Perkalian dievaluasi sebelum penjumlahan.
console.log(2 + 3 * 4);
// Tanda kurung mengubah urutan evaluasi.
console.log((2 + 3) * 4);
// Pengurangan dievaluasi kiri ke kanan.
console.log(10 - 4 - 3);
// Pangkat dievaluasi kanan ke kiri.
console.log(2 ** 3 ** 2);
// Modulo dan perbandingan bergabung dengan operator logika.
console.log(3 + 4 > 5 && 10 % 3 === 1);
// ?? dipadukan dengan || setelah diberi tanda kurung.
const inputPengguna = null;
console.log((inputPengguna ?? 0) || "belum ada");Output yang Dihasilkan:
14
20
3
512
true
belum adaMari kita telaah baris-baris pentingnya:
- Baris 5 (
console.log(2 + 3 * 4);):*berada di atas+pada tabel, sehingga3 * 4dihitung lebih dulu menjadi12, lalu2 + 12menghasilkan14. - Baris 8 (
console.log((2 + 3) * 4);): tanda kurung memaksa urutan evaluasi lain —2 + 3menjadi5, lalu5 * 4menghasilkan20. Tanda kurung berada di urutan tertinggi dan selalu bisa kita pakai untuk menegaskan maksud. - Baris 11 (
console.log(10 - 4 - 3);): kedua operator setara, sehingga aturan pemasangan (associativity) yang menentukan. Pengurangan dipasang kiri-ke-kanan:(10 - 4) - 3menghasilkan3, bukan10 - (4 - 3)yang bernilai9. - Baris 14 (
console.log(2 ** 3 ** 2);): operator**adalah pengecualian — ia dipasang kanan-ke-kiri. Ekspresi itu dibaca2 ** (3 ** 2)=2 ** 9=512, bukan(2 ** 3) ** 2=64. - Baris 17 (
console.log(3 + 4 > 5 && 10 % 3 === 1);): ekspresi paling padat di berkas ini. Urutan kerja engine:3 + 4menjadi7;%lebih tinggi dari===, sehingga10 % 3menjadi1lalu dibandingkan dengan=== 1; kini ekspresinya tinggal7 > 5 && true === true, dan hasil akhirnyatrue. - Baris 21 (
console.log((inputPengguna ?? 0) || "belum ada");):??berada di bawah||, sehingga tanpa kurung gabungan ini memang ditolak engine. Dengan kurung,inputPengguna ?? 0dievaluasi dulu menjadi0, lalu0 || "belum ada"menghasilkan"belum ada".
Unary Minus Bertemu Pangkat #
Dua operator pada tabel di atas punya hubungan istimewa: unary minus dan pangkat. Ketika keduanya bertemu langsung tanpa tanda kurung — seperti console.log(-2 ** 2); — engine menolak programnya sebelum eksekusi dengan pesan:
SyntaxError: Unary operator used immediately before exponentiation expression. Parenthesis must be used to disambiguate operator precedenceEkspresi -2 ** 2 bisa dibaca dua cara — “negasi dari 2 ** 2” (hasilnya -4) atau “dua negatif dipangkatkan dua” (hasilnya 4) — dan keduanya berbeda. Seperti pada kasus ?? berikutnya, engine menuntut kejelasan lewat tanda kurung:
console.log((-2) ** 2);
console.log(-(2 ** 2));Output yang Dihasilkan:
4
-4Kedua bentuk kini sah dan berbeda hasilnya sesuai posisi kurungnya: (-2) ** 2 memangkatkan dua negatif menjadi 4, sedangkan -(2 ** 2) memangkatkan dua dahulu lalu menegasi hasilnya menjadi -4.
Ketika ?? Dipadukan Tanpa Tanda Kurung #
Aturan poin 6 di atas bersifat mutlak: ?? tidak boleh bersebelahan langsung dengan || atau &&. Berkas berikut sengaja melanggarnya:
// gabungan-tanpa-kurung.js
// Demonstrasi: ?? tidak boleh dipadukan langsung dengan || tanpa tanda kurung.
const nilaiA = null;
const nilaiB = 0;
const hasil = nilaiA ?? nilaiB || "cadangan";
console.log(hasil);Jika dijalankan, program tidak pernah sampai ke tahap eksekusi. Node berhenti saat membaca sintaks dan menampilkan pesan berikut (inti transkripnya):
const hasil = nilaiA ?? nilaiB || "cadangan";
^^
SyntaxError: Unexpected token '||'Tanda ^^ pada transkrip menunjuk langsung ke || — engine tidak mau menebak maksud kita: apakah yang dimaksud (nilaiA ?? nilaiB) || "cadangan" atau nilaiA ?? (nilaiB || "cadangan")? Kedua pembacaan itu menghasilkan nilai berbeda (0 versus "cadangan"), dan alih-alih memilih salah satu secara senyap, spesifikasi JavaScript memaksa penulisnya menyatakan maksud lewat tanda kurung. Padanan dengan && diperlakukan sama: a ?? b && c juga ditolak dengan SyntaxError: Unexpected token '&&'.
Dengan urutan evaluasi ini kita sudah tahu persis bagaimana engine membaca satu baris kode. Satu area berbahaya tersisa yang menyangkut aturan antartipe: operator kesetaraan == dan === beserta konversi tipe senyapnya — topik penutup section ini, chapter Equality dan Type Coercion.
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
gabungan-tanpa-kurung.js
Unduh berkas// gabungan-tanpa-kurung.js
// Demonstrasi: ?? tidak boleh dipadukan langsung dengan || tanpa tanda kurung.
const nilaiA = null;
const nilaiB = 0;
const hasil = nilaiA ?? nilaiB || "cadangan";
console.log(hasil);
urutan-hitung.js
Unduh berkas// urutan-hitung.js
// Membuktikan urutan evaluasi operator dengan ekspresi campur.
// Perkalian dievaluasi sebelum penjumlahan.
console.log(2 + 3 * 4);
// Tanda kurung mengubah urutan evaluasi.
console.log((2 + 3) * 4);
// Pengurangan dievaluasi kiri ke kanan.
console.log(10 - 4 - 3);
// Pangkat dievaluasi kanan ke kiri.
console.log(2 ** 3 ** 2);
// Modulo dan perbandingan bergabung dengan operator logika.
console.log(3 + 4 > 5 && 10 % 3 === 1);
// ?? dipadukan dengan || setelah diberi tanda kurung.
const inputPengguna = null;
console.log((inputPengguna ?? 0) || "belum ada");