Function yang hanya mencetak ke console memang membantu, tetapi hasilnya terbuang begitu saja: nilai yang sudah dihitung tidak bisa dipakai bagian program lain. Bayangkan hitungPajak yang mencetak 11000 — function lain yang butuh angka itu tetap tidak bisa mengambilnya dari layar. Jalur keluar yang benar adalah statement return: function menghitung, lalu menyerahkan hasilnya kepada pemanggil untuk disimpan, dihitung ulang, atau diteruskan.

Chapter ini membedah empat sifat return sekaligus: kemampuannya menghentikan eksekusi (dan pola early return yang pseudocode-nya sudah kita lihat di akhir section Control Flow), perilaku return tanpa nilai, konsekuensi function tanpa return, serta cara mengirim lebih dari satu nilai sekaligus. Satu cara membaca yang membantu sepanjang chapter: pandang pemanggilan function sebagai jeda. Program pemanggil berhenti sesaat, badan function berjalan, dan statement return adalah titik di mana jeda itu berakhir — nilai yang ditentukan di sana menjadi pengganti seluruh pemanggilan.

Return Menghentikan Eksekusi #

Statement return melakukan dua hal sekaligus dalam satu langkah: menentukan nilai yang dikirim ke pemanggil, dan mengakhiri badan function pada baris itu. Sifat kedua inilah fondasi pola early return — urutan pemeriksaan yang sudah kita rancang sebagai pseudocode di section Control Flow kini bisa dituliskan sebagai kode sungguhan, dengan data kasus pendaftaran yang sama:

// nilai-kembali.js
// Statement return: menghentikan eksekusi dan mengirim hasil ke pemanggil.

// --- 1. early return: guard clause dari pseudocode section Control Flow ---
function verifikasiPendaftaran(usia, sudahBayar, kontakDarurat) {
  if (usia < 17) {
    return "Usia minimal 17 tahun";
  }
  if (!sudahBayar) {
    return "Selesaikan pembayaran terlebih dahulu";
  }
  if (kontakDarurat === "") {
    return "Isi kontak darurat terlebih dahulu";
  }
  return "Pendaftaran lengkap - kartu peserta dicetak";
}

console.log(verifikasiPendaftaran(20, true, "0812-3456-7890"));
console.log(verifikasiPendaftaran(16, true, "0813-2222-3333"));
console.log(verifikasiPendaftaran(20, false, "0812-3456-7890"));

// --- 2. return menghentikan function; kode setelahnya tidak berjalan ---
function cekStok(jumlah) {
  if (jumlah <= 0) {
    return "Stok habis";
  }
  console.log("Stok tersedia:", jumlah);
  return "Siap dikirim";
}

console.log(cekStok(0));
console.log(cekStok(12));

// --- 3. return tanpa nilai, atau tanpa return, menghasilkan undefined ---
function catatLog(pesan) {
  console.log("LOG:", pesan);
  return;
}

const hasilCatat = catatLog("sistem diperbarui");
console.log("Kembalian catatLog:", hasilCatat);

function duaKaliTanpaReturn(angka) {
  const hasil = angka * 2; // dihitung, tetapi tidak dikirim ke mana pun
}

console.log("Kembalian duaKaliTanpaReturn:", duaKaliTanpaReturn(7));

// --- 4. beberapa nilai sekaligus: dibungkus array ---
function ukuranKotak(panjang, lebar) {
  const luas = panjang * lebar;
  const keliling = 2 * (panjang + lebar);
  return [luas, keliling];
}

const hasilKotak = ukuranKotak(5, 3);
console.log("Luas:", hasilKotak[0]);
console.log("Keliling:", hasilKotak[1]);

// --- 5. beberapa nilai sekaligus: dibungkus object ---
function dataSiswa(nama, nilai) {
  return { nama: nama, status: nilai >= 75 ? "lulus" : "remedial" };
}

const siswa = dataSiswa("Siti", 88);
console.log("Nama:", siswa.nama, "- Status:", siswa.status);

Output yang Dihasilkan:

text
Pendaftaran lengkap - kartu peserta dicetak
Usia minimal 17 tahun
Selesaikan pembayaran terlebih dahulu
Stok habis
Stok tersedia: 12
Siap dikirim
LOG: sistem diperbarui
Kembalian catatLog: undefined
Kembalian duaKaliTanpaReturn: undefined
Luas: 15
Keliling: 16
Nama: Siti - Status: lulus

Mari kita telaah apa yang terjadi pada baris-baris kode di atas:

  1. Baris 5–16 (verifikasiPendaftaran): tiga guard clause berurutan — masing-masing satu if yang langsung return. Data pertama (20, true, terisi) lolos dari ketiganya dan mencapai return terakhir: Pendaftaran lengkap.... Data kedua berhenti di guard pertama, data ketiga di guard kedua. Kedalaman logika tetap satu level, persis tujuan perataan kondisi di section Control Flow.
  2. Baris 23–29 (cekStok): pemanggilan cekStok(0) berhenti di baris 25 — baris 27 tidak sempat berjalan, sehingga Stok tersedia: hanya tercetak satu kali (untuk cekStok(12)). Ini bukti paling gamblang bahwa return menghentikan badan function di tengah jalan.
  3. Baris 35–41 (catatLog dan pemanggilnya): return; tanpa nilai sah ditulis. Hasilnya sama dengan tidak menulis return: variabel hasilCatat berisi undefined.
  4. Baris 43–47 (duaKaliTanpaReturn): perhitungan angka * 2 tetap berjalan di dalam function, tetapi hasilnya tidak pernah dikirim ke pemanggil — 14 hilang bersama berakhirnya function. Function yang lupa return adalah sumber bug klasik: program berjalan tanpa error, tetapi hasil yang diharapkan berupa undefined.
  5. Baris 50–58 (ukuranKotak): satu return mengirim satu nilai, tetapi nilai itu boleh berupa array berisi dua angka. Pemanggil membaca anggotanya lewat indeks: hasilKotak[0] untuk luas dan hasilKotak[1] untuk keliling.
  6. Baris 61–66 (dataSiswa): variasi kedua membungkus hasil dalam object literal dengan dua properti, lalu dibaca lewat titik: siswa.nama dan siswa.status. Kita baru sekilas menyentuh object di sini; struktur lengkapnya menanti di section Objects.

Untuk dua nilai sekaligus, array dan object sama-sama sah — pilihannya soal keterbacaan. Array unggul saat urutan jelas dan pembaca sudah tahu posisinya ([0] luas, [1] keliling); object unggul saat datanya punya makna berbeda-beda, karena siswa.status menerangkan dirinya sendiri sementara siswa[1] memaksa pembaca mengingat urutan. Semakin banyak nilai yang dikirim, semakin berat tekanan mengingat urutan indeks — dan semakin sebaiknya object dipilih.

Return di Tengah Loop #

Sifat penghenti return juga bekerja di dalam loop — dan sering menggantikan kombinasi break plus variabel penanda. Function pencarian berikut berhenti seketika begitu target ditemukan; tidak perlu menelusuri sisa daftar:

js
function cariBuah(daftar, target) {
  for (let i = 0; i < daftar.length; i++) {
    if (daftar[i] === target) {
      return "Ketemu di indeks " + i;
    }
  }
  return "Tidak ada";
}

console.log(cariBuah(["apel", "mangga", "jeruk"], "mangga"));
console.log(cariBuah(["apel", "mangga", "jeruk"], "durian"));

Output yang Dihasilkan:

text
Ketemu di indeks 1
Tidak ada

Ada dua pintu keluar dan keduanya return: yang satu di dalam loop (jalur berhasil), yang satu setelahnya (jalur gagal). return "Tidak ada" hanya terjangkau bila loop selesai tanpa menemukan apa pun — bila ditemukan, function sudah menutup diri di tengah jalan. Perbandingannya dengan pola flag ditemukan plus break yang kita pakai di section Control Flow: satu statement menggantikan dua variabel.

Nilai Kembalian Merantai ke Function Lain #

Sesungguhnya dari return value adalah kemampuannya merantai: hasil satu function langsung menjadi masukan function berikutnya, tanpa perlu variabel perantara yang memenuhi layar. Pola ini mendiami kode nyata — hitung, lalu format; ambil, lalu olah:

js
function hitungDiskon(harga, persen) {
  return harga - (harga * persen) / 100;
}

function formatRupiah(angka) {
  return "Rp" + angka;
}

const bayar = formatRupiah(hitungDiskon(120000, 25));
console.log(bayar);

Output yang Dihasilkan:

text
Rp90000

Eksekusinya membaca dari dalam ke luar: hitungDiskon(120000, 25) berjalan lebih dulu dan mengirim 90000; angka itu menjadi argument formatRupiah, yang mengirim "Rp90000"; akhirnya teks jadi disimpan ke bayar. Kedua function tadi masing-masing kecil dan bisa diuji sendiri, tetapi dirangkai menjadi alur kerja yang utuh — kebebasan merangkai hanya ada karena keduanya return, bukan sekadar mencetak.

Return Bukan console.log #

Kesalahan pemula yang paling sering: menyamakan return dengan console.log. Keduanya hidup di dunia berbeda, dan perbedaannya paling tampak saat hasil function disimpan ke variabel:

js
function sapaA(nama) {
  console.log("Halo, " + nama);
}

function sapaB(nama) {
  return "Halo, " + nama;
}

const hasilA = sapaA("Budi");
const hasilB = sapaB("Budi");
console.log("hasilA:", hasilA);
console.log("hasilB:", hasilB);
console.log("Panjang hasilB:", hasilB.length);

Output yang Dihasilkan:

text
Halo, Budi
hasilA: undefined
hasilB: Halo, Budi
Panjang hasilB: 10

Empat baris keluaran itu merangkum semuanya. sapaA("Budi") langsung mencetak Halo, Budi saat dipanggil, tetapi yang diterima pemanggil hanyalah undefined — teksnya tidak pernah kembali ke program. sapaB("Budi") tidak mencetak apa pun; teksnya diserahkan ke hasilB, yang kemudian bisa diukur (length bernilai 10) dan diteruskan ke function lain. Function yang benar melakukan perhitungan dan return; urusan menampilkan diserahkan kepada pemanggil.

Dengan return, jalur masuk dan jalur keluar function sudah lengkap. Sisa satu celah praktis: banyak function punya parameter yang sering kali tidak dikirim pemanggil — dan menuliskan pemeriksaan untuk setiap kemungkinan itu melelahkan. Chapter berikutnya menyediakan solusi bawaan bahasanya: default parameters. Ketika itu terjadi, dua pola chapter ini akan terus menemani: guard clause yang menghentikan jalur salah sejak awal, dan function yang jujur mengembalikan nilainya alih-alih sekadar mencetaknya.

Berkas Sumber

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

nilai-kembali.js

Unduh berkas
javascript
// nilai-kembali.js
// Statement return: menghentikan eksekusi dan mengirim hasil ke pemanggil.

// --- 1. early return: guard clause dari pseudocode section Control Flow ---
function verifikasiPendaftaran(usia, sudahBayar, kontakDarurat) {
  if (usia < 17) {
    return "Usia minimal 17 tahun";
  }
  if (!sudahBayar) {
    return "Selesaikan pembayaran terlebih dahulu";
  }
  if (kontakDarurat === "") {
    return "Isi kontak darurat terlebih dahulu";
  }
  return "Pendaftaran lengkap - kartu peserta dicetak";
}

console.log(verifikasiPendaftaran(20, true, "0812-3456-7890"));
console.log(verifikasiPendaftaran(16, true, "0813-2222-3333"));
console.log(verifikasiPendaftaran(20, false, "0812-3456-7890"));

// --- 2. return menghentikan function; kode setelahnya tidak berjalan ---
function cekStok(jumlah) {
  if (jumlah <= 0) {
    return "Stok habis";
  }
  console.log("Stok tersedia:", jumlah);
  return "Siap dikirim";
}

console.log(cekStok(0));
console.log(cekStok(12));

// --- 3. return tanpa nilai, atau tanpa return, menghasilkan undefined ---
function catatLog(pesan) {
  console.log("LOG:", pesan);
  return;
}

const hasilCatat = catatLog("sistem diperbarui");
console.log("Kembalian catatLog:", hasilCatat);

function duaKaliTanpaReturn(angka) {
  const hasil = angka * 2; // dihitung, tetapi tidak dikirim ke mana pun
}

console.log("Kembalian duaKaliTanpaReturn:", duaKaliTanpaReturn(7));

// --- 4. beberapa nilai sekaligus: dibungkus array ---
function ukuranKotak(panjang, lebar) {
  const luas = panjang * lebar;
  const keliling = 2 * (panjang + lebar);
  return [luas, keliling];
}

const hasilKotak = ukuranKotak(5, 3);
console.log("Luas:", hasilKotak[0]);
console.log("Keliling:", hasilKotak[1]);

// --- 5. beberapa nilai sekaligus: dibungkus object ---
function dataSiswa(nama, nilai) {
  return { nama: nama, status: nilai >= 75 ? "lulus" : "remedial" };
}

const siswa = dataSiswa("Siti", 88);
console.log("Nama:", siswa.nama, "- Status:", siswa.status);