Tahu sintaks dan bisa menulis kode yang bagus itu dua keterampilan yang berbeda. Sampai di titik ini, kamu sudah bisa mendeklarasikan variabel, menulis fungsi, melakukan perulangan pada array, dan mengakses isi objek — bagian mekanisnya sudah kamu kuasai. Tapi kode yang sekadar jalan bukanlah garis finis. Kode beneran itu lebih sering dibaca daripada ditulis: oleh rekan kerja, oleh dirimu sendiri enam bulan ke depan, dan oleh siapa pun yang harus membenahi bug jam 2 dini hari. Tujuan artikel ini adalah mengubah bahasa yang sudah kamu kuasai menjadi kode yang rapi, mudah ditebak, dan menyenangkan untuk dirawat.
Nggak ada yang aneh-aneh di sini. Ini semua kebiasaan sehari-hari yang dipakai developer berpengalaman hampir tanpa berpikir lagi — dan begitu kamu terbiasa, kamu pun bakal begitu. Kita bakal membangun semuanya di atas materi dari artikel-artikel sebelumnya, jadi kalau ada konsep yang masih terasa goyah, tautan di sepanjang jalan menunjuk balik ke dasarnya.
Pakai const sebagai default, let saat perlu, jangan pakai var
Ini kebiasaan tunggal yang paling besar dampaknya, sekaligus yang paling gampang dijalankan. Kita sudah bahas ketiga keyword ini di artikel variabel dan tipe data; praktiknya sederhana:
- Pilih
constlebih dulu, selalu. - Pindah ke
lethanya kalau kamu memang butuh menugaskan ulang variabelnya. - Jangan pernah pakai
vardi kode baru.
const tarifPajak = 0.11; // nggak pernah berubah → const
let totalBerjalan = 0; // ditugaskan ulang di perulangan → let
for (const item of keranjang) {
totalBerjalan += item.harga;
}
Kenapa const jadi default? Ini bukan soal nilainya dibekukan — ini soal niat. Saat pembaca melihat const, dia langsung tahu nama itu bakal selalu menunjuk ke hal yang sama, jadi dia nggak perlu repot melacaknya di kepala. let jadi semacam penanda kecil yang bilang “perhatikan yang ini, dia bisa berubah.” Sinyal itu sungguh berguna, dan const membuatnya jadi default, bukan pengecualian.
const bukan berarti nilainya dibekukan
const menghalangimu menugaskan ulang variabelnya, bukan mengubah isi dari apa yang ditunjuknya. Pada objek atau array, isinya masih bisa kamu ubah:
const pengguna = { nama: "John Doe" };
pengguna.nama = "Jane Doe"; // boleh — kita mengubah isi objeknya
pengguna = {}; // TypeError — kita coba menugaskan ulangJadi const menjamin ikatan namanya stabil, bukan datanya jadi nggak bisa diubah. Kalau kamu butuh objek yang benar-benar read-only, itu pakai alat lain (Object.freeze), bukan tugas const.
var layak dihindari karena alasan konkret: dia function-scoped dan di-hoist dengan cara yang diam-diam memicu bug, sedangkan let dan const itu block-scoped dan berperilaku sesuai yang kamu harapkan. Ada artikel khusus soal kenapa perbedaan ini penting — untuk kode sehari-hari, cukup tinggalkan var di masa lalu.
Beri nama yang jelas
Nama yang baik adalah dokumentasi yang nggak pernah kedaluwarsa. Variabel bernama d nggak memberitahu apa-apa; hariSampaiKedaluwarsa memberitahu segalanya. Ketukan keyboard tambahan yang sedikit itu langsung balik modal begitu ada orang membaca kodenya.
// Samar — ini apa? satuannya apa?
const t = 86400;
function htg(a, b) { return a * b; }
// Jelas — namanya menjelaskan dirinya sendiri
const detikPerHari = 86400;
function hitungTotal(harga, jumlah) {
return harga * jumlah;
}
Beberapa konvensi yang dipakai seluruh dunia JavaScript, supaya kodemu terlihat akrab buat siapa pun:
- Variabel dan fungsi pakai
camelCase:namaPengguna,hitungTotal. - Konstanta yang nilainya benar-benar tetap kadang ditulis
UPPER_SNAKE_CASE:MAX_RETRIES,API_BASE_URL. - Boolean enak dibaca dengan awalan
is,has, ataucan:isActive,hasPermission,canEdit. - Fungsi diawali kata kerja karena dia melakukan sesuatu:
getUser,sendEmail,formatHarga.
Jangan menyingkat demi hemat tempat, dan jangan takut nama yang agak panjang. cnt menghemat tiga karakter tapi membebani setiap pembaca berikutnya dengan tebak-tebakan sesaat. count jauh lebih baik.
Buat fungsi tetap kecil dan fokus
Kita sudah menggali fungsi di artikel fungsi. Lapisan praktik terbaik di atasnya sederhana: sebuah fungsi sebaiknya melakukan satu hal, dan namanya harus memberitahu hal apa itu. Begitu sebuah fungsi mulai menangani tiga pekerjaan yang nggak nyambung, pecah saja.
// Terlalu banyak kerjaan: validasi, hitung, DAN format sekaligus
function prosesPesanan(pesanan) {
if (!pesanan.items.length) throw new Error("Pesanan kosong");
let total = 0;
for (const item of pesanan.items) total += item.harga * item.jumlah;
return "Total: Rp " + total.toLocaleString("id-ID");
}
// Dipecah jadi bagian-bagian fokus — masing-masing gampang dibaca dan diuji
function validasiPesanan(pesanan) {
if (!pesanan.items.length) throw new Error("Pesanan kosong");
}
function hitungTotal(items) {
return items.reduce((jumlah, item) => jumlah + item.harga * item.jumlah, 0);
}
function formatRupiah(nilai) {
return "Rp " + nilai.toLocaleString("id-ID");
}
Fungsi kecil lebih gampang dinamai, lebih gampang dipakai ulang, dan jauh lebih gampang di-debug — saat ada yang rusak, kamu langsung tahu potongan kecil mana yang harus dilihat. Patokan praktisnya: kalau kamu kesulitan menamai sebuah fungsi karena dia melakukan banyak hal, itu kode yang sedang memberitahumu untuk memecahnya.
Hindari nesting dalam dengan early return
Blok if yang bertumpuk dalam-dalam itu susah diikuti karena kamu harus menahan semua kondisinya di kepala sekaligus. Obatnya adalah early return (sering disebut juga guard clause): tangani kasus-kasus pengecualian lebih dulu lalu langsung keluar, supaya logika utamanya nggak terkubur di balik indentasi.
// Susah diikuti — kerja sebenarnya ada di kedalaman empat tingkat
function getDiskon(pengguna) {
if (pengguna) {
if (pengguna.isActive) {
if (pengguna.pembelian > 10) {
return 0.2;
}
}
}
return 0;
}
// Datar dan gampang dibaca — tangani kasus "tidak" dulu, baru lanjut
function getDiskon(pengguna) {
if (!pengguna) return 0;
if (!pengguna.isActive) return 0;
if (pengguna.pembelian <= 10) return 0;
return 0.2;
}
Versi kedua terbaca dari atas ke bawah seperti checklist. Tiap guard clause mengupas satu kasus lalu minggir, jadi pas kamu sampai di bawah, jalur normalnya berdiri sendirian tanpa indentasi yang menutupinya.
Pakai perbandingan ketat (===)
JavaScript punya dua operator perbandingan, dan kamu sebaiknya hampir selalu pakai yang ketat. == (perbandingan longgar) berusaha mengubah kedua nilai ke tipe yang sama sebelum membandingkan, dan itu menghasilkan hasil yang bikin kaget. === (perbandingan ketat) membandingkan nilai dan tipe, tanpa konversi apa pun — persis yang biasanya kamu mau.
0 == ""; // true — keduanya dipaksa jadi falsy. Mengagetkan!
0 == "0"; // true — string "0" diubah jadi angka
"" == "0"; // false — lho, kok?
null == undefined; // true
0 === ""; // false — tipe beda, nggak ada konversi
"0" === 0; // false — jelas dan bisa ditebak
Aturan == yang longgar itu labirin penuh kasus pinggiran yang bahkan developer berpengalaman pun nggak hafal di luar kepala. Dengan memakai === di mana-mana, kamu menghindari seluruh masalah itu. Hal yang sama berlaku untuk !== ketimbang !=.
Linter menangkap ini untukmu
Kamu nggak perlu mengingat tiap aturan secara manual. Linter seperti ESLint menandai ==, variabel yang nggak terpakai, nama yang belum dideklarasikan, dan puluhan kesalahan lain selagi kamu mengetik — banyak editor langsung menggarisbawahinya seketika. Memasangnya adalah satu hal dengan daya ungkit tertinggi untuk kualitas kode, karena dia menegakkan kebiasaan-kebiasaan ini secara otomatis ketimbang bergantung pada ingatanmu.
Tangani error, jangan diabaikan
Kode yang mengandaikan semuanya selalu berjalan mulus itu rapuh. Permintaan jaringan bisa gagal, JSON bisa datang dalam bentuk rusak, pengguna bisa mengetik hal yang ngawur. Data yang kamu olah nggak selalu sama dengan data yang kamu harapkan, jadi siapkan rencana untuk jalur yang nggak mulus.
Bungkus operasi berisiko dengan try...catch, dan jangan pernah menelan error diam-diam:
// Buruk — kalau parsing gagal, program crash atau berperilaku aneh
const data = JSON.parse(inputMentah);
// Baik — tangani kegagalannya secara sadar
try {
const data = JSON.parse(inputMentah);
render(data);
} catch (error) {
console.error("Gagal mem-parsing input:", error.message);
showFallbackUI();
}
Hal terburuk yang bisa kamu lakukan adalah menangkap error lalu nggak berbuat apa-apa dengannya — blok catch {} yang kosong menyembunyikan masalah ketimbang menyelesaikannya, dan mengubah crash yang jelas menjadi bug yang sunyi dan membingungkan di kemudian hari. Kalau kamu menangkap error, lakukan sesuatu: catat di log, tampilkan pesan ke pengguna, atau mundur ke nilai default. Mau menggali lebih dalam? Pola penanganan data dari awal seri ini berpadu alami dengan penanganan error yang solid.
Lebih baik method array ketimbang perulangan manual
Kamu sudah belajar perulangan for klasik di artikel perulangan, dan dia masih jadi alat yang tepat di sebagian kasus. Tapi untuk pekerjaan yang paling umum — mengubah sebuah daftar, menyaringnya, atau menjumlahkannya — method array bawaan menyatakan maksudmu jauh lebih jelas ketimbang perulangan rakitan sendiri dengan penghitung dan array sementara.
const hargaList = [100, 250, 80, 300];
// Perulangan manual — jalan, tapi berisik
const denganPajak = [];
for (let i = 0; i < hargaList.length; i++) {
denganPajak.push(hargaList[i] * 1.11);
}
// Deklaratif — terbaca sesuai maksudnya: "petakan tiap harga jadi harga * 1.11"
const denganPajak = hargaList.map((harga) => harga * 1.11);
// Filter dan reduce terbaca sama bersihnya
const mahal = hargaList.filter((harga) => harga > 150);
const total = hargaList.reduce((jumlah, harga) => jumlah + harga, 0);
map, filter, dan reduce menggambarkan apa yang kamu mau ketimbang bagaimana cara mengulangnya, dan justru itulah yang membuatnya lebih gampang dibaca. Method ini juga menghindari kesalahan index meleset satu yang sering diundang oleh perulangan manual. Simpan perulangan for biasa untuk kasus yang memang membutuhkannya — keluar lebih awal, langkah pengulangan yang rumit — dan biarkan method menangani transformasi sehari-hari.
Jangan mengulang-ulang kode
Kalau kamu mendapati dirimu menyalin-tempel beberapa baris yang sama, itu pertanda untuk mengeluarkannya jadi sebuah fungsi. Kode yang berulang bukan cuma lebih panjang — dia jebakan perawatan, karena pada hari kamu perlu memperbaiki logika itu, kamu harus mengingat tiap tempat kamu menempelkannya.
// Pengulangan — logika format yang sama, tiga kali
const label1 = "Rp " + harga1.toLocaleString("id-ID");
const label2 = "Rp " + harga2.toLocaleString("id-ID");
const label3 = "Rp " + harga3.toLocaleString("id-ID");
// Satu sumber kebenaran — perbaiki sekali, beres di semua tempat
function formatRupiah(nilai) {
return "Rp " + nilai.toLocaleString("id-ID");
}
const label1 = formatRupiah(harga1);
const label2 = formatRupiah(harga2);
const label3 = formatRupiah(harga3);
Prinsip ini sering disebut DRY — Don’t Repeat Yourself, alias jangan mengulang dirimu sendiri. Jangan dibawa ke ekstrem yang konyol (sedikit duplikasi itu wajar, dan memaksa dua hal yang nyaris nggak berkaitan berbagi kode bisa lebih buruk ketimbang menyalinnya), tapi saat logika nyata yang sama muncul tiga kali, beri dia nama dan rumah sendiri.
Tulis kode supaya manusia bisa membacanya
Komputer menjalankan apa pun yang kamu berikan, tapi manusia harus memahaminya. Sentuhan-sentuhan kecil yang membuat kode jelas itu menumpuk jadi besar:
- Komentari kenapa-nya, bukan apa-nya. Kodenya sudah menunjukkan apa yang dilakukannya; komentar yang baik menjelaskan kenapa dilakukan dengan cara itu.
// tambah 1 ke iitu sampah;// coba ulang sekali sebelum menyerah, API-nya suka gagal di panggilan pertamaitu emas. - Pakai ruang kosong untuk mengelompokkan baris yang berkaitan. Satu baris kosong di antara langkah-langkah logis berfungsi seperti jeda paragraf.
- Konsisten. Pilih satu gaya — tanda kutip, indentasi, titik koma — dan tahan di seluruh file. Formatter seperti Prettier melakukannya untukmu secara otomatis.
// Apa: mubazir, kodenya sudah mengatakan ini
let count = 0; // set count jadi nol
// Kenapa: menjelaskan keputusan yang nggak bisa diutarakan kode
let retries = 0;
const MAX_RETRIES = 3; // 3 karena layanan upstream sering timeout sekitar percobaan ke-4
Konsistensi lebih penting ketimbang pilihan tunggal mana pun. Mau pakai titik koma atau nggak, kutip tunggal atau ganda, dua spasi atau empat — yang penting seluruh basis kode sepakat, sehingga pembaca nggak pernah perlu menebak apakah suatu perbedaan itu bermakna.
Biarkan alat menangani hal yang membosankan
Dua alat melakukan kerja yang menjemukan supaya kamu bisa fokus ke logika: formatter (seperti Prettier) menjaga spasi, kutip, dan indentasi seragam secara otomatis, dan linter (seperti ESLint) menangkap kemungkinan bug dan pola buruk. Pasang sekali dan keduanya berjalan tiap kali kamu menyimpan. Saat kamu bekerja dengan data terstruktur seperti JSON, sebuah formatter sekaligus validator JSON daring berguna untuk cepat mengecek apakah sebuah payload sudah berbentuk benar sebelum kamu men-debug kodemu.
Hindari mengotori scope global
Saat kamu mendeklarasikan sesuatu di tingkat paling atas tanpa kehati-hatian, hal itu hidup di scope global tempat skrip lain mana pun bisa membacanya atau menimpanya. Itu resep buat tabrakan nama dan bug yang bikin pusing dilacak. Berkat fungsi dan modul modern, obatnya gampang: simpan variabel di scope sekecil mungkin yang masih berfungsi, dan pakai ES module supaya tiap file punya ruang nama pribadinya sendiri.
// Mengotori scope global — apa pun bisa menimpa `total`
total = 0;
function tambah(n) { total += n; }
// Terbungkus — `total` hidup hanya di tempat ia dibutuhkan
function jumlahkanSemua(angkaList) {
let total = 0;
for (const n of angkaList) total += n;
return total;
}
Mendeklarasikan variabel di scope sesempit mungkin — di dalam fungsi atau blok yang memakainya — menjaga tiap bagian programmu tetap mandiri. Bagian-bagian yang mandiri nggak saling menginjak, dan justru itulah yang membuat basis kode besar tetap bisa dikelola.
Menyatukan semuanya
Berikut tugas kecil yang sama ditulis dua kali — sekali asal-asalan, sekali dengan kebiasaan di atas — supaya kamu bisa melihat bagaimana semuanya bertumpuk jadi besar:
// Sebelum: jalan, tapi kasar
function p(d) {
var r = [];
for (var i = 0; i < d.length; i++) {
if (d[i].active == true) {
r.push(d[i].name + ": Rp " + d[i].price);
}
}
return r;
}
// Sesudah: hasil sama, jauh lebih jelas
function formatProdukAktif(produkList) {
return produkList
.filter((produk) => produk.isActive)
.map((produk) => `${produk.nama}: Rp ${produk.harga.toLocaleString("id-ID")}`);
}
Versi kedua memakai nama yang deskriptif, method array yang ramah const, perbandingan ketat lewat boolean yang bersih, dan mengerjakan satu tugasnya dengan jelas. Dia lebih pendek sekaligus lebih gampang dipahami — itulah hasil dari kebiasaan yang baik. Kebiasaan ini nggak memperlambatmu; begitu jadi otomatis, justru membuatmu lebih cepat, karena kamu menghabiskan lebih sedikit waktu menerka-nerka kodemu sendiri di masa lalu.
Penutup
Praktik terbaik bukan aturan yang dipaksakan untuk menyulitkan hidupmu — dia jalan pintas menuju kode yang lebih gampang dibaca, lebih aman diubah, dan lebih cepat di-debug. Yang layak kamu tanamkan jadi kebiasaan:
- Deklarasikan dengan
constsebagai default,lethanya saat menugaskan ulang, dan jangan pernahvar— tapi ingatconstmenghalangi penugasan ulang, bukan perubahan isi. - Beri nama yang jelas dengan
camelCase, fungsi diawali kata kerja, dan booleanis/has— nama itu dokumentasi gratis. - Jaga fungsi tetap kecil dan fokus pada satu pekerjaan, dan ratakan nesting dengan early return.
- Pakai
===(perbandingan ketat) untuk menghindari kejutan dari konversi tipe. - Tangani error dengan
try...catchdan jangan pernah menelannya diam-diam. - Lebih utamakan
map/filter/reduceketimbang perulangan manual untuk olah daftar sehari-hari. - Jangan mengulang-ulang diri — keluarkan logika yang berulang jadi fungsi bernama.
- Tulis untuk manusia: komentari kenapa-nya, tetap konsisten, dan biarkan formatter serta linter menangani sisanya.
- Jaga scope tetap kecil dan pakai modul supaya tiap bagianmu tetap mandiri.
Kamu nggak harus menyempurnakan semua ini dalam semalam. Ambil satu atau dua dulu — const sebagai default dan === di mana-mana adalah titik awal yang bagus — dan biarkan keduanya jadi otomatis sebelum menambah yang berikutnya. Kode yang baik adalah keterampilan yang kamu bangun satu kebiasaan demi satu kebiasaan, dan kamu sudah punya semua yang dibutuhkan untuk mulai.