Belajar dengan membaca secara berurutan

Function Declaration dan Function Expression — Argument dan return

Pelajari function declaration, argument dan return, function expression, serta alasan function tanpa return menghasilkan undefined.

Kalau rumus harga termasuk pajak kamu tulis langsung di tiga tempat — daftar produk, keranjang, dan konfirmasi pesanan — maka saat tarif pajak berubah, ketiganya harus diperbaiki, dan layar yang terlewat akan tetap menampilkan harga lama.

Artikel ini membahas function declaration yang memberi nama pada sebuah proses supaya bisa dipanggil, function expression yang menyimpan function di variabel sebagai value, dan value yang dikembalikan return.

Memberi Nama pada Proses Supaya Bisa Dipanggil — function Declaration dan Parameter

Proses menghitung harga termasuk pajak untuk tiap produk selalu sama; yang berbeda hanya harga satuannya. Karena yang berubah cuma harga yang dioper, kamu bisa memberi nama pada perhitungannya, lalu daftar produk maupun keranjang cukup memanggil nama itu.

Function (sekumpulan proses yang diberi nama supaya bisa dipanggil berapa kali pun) dideklarasikan dalam bentuk function nama(parameter) { body }. Parameter di dalam tanda kurung adalah variabel yang menerima value setiap kali function dipanggil, dan value yang ditulis setelah return (return value) dikirim kembali ke pemanggil.

// Beri nama taxIncluded pada proses menghitung harga termasuk pajak
function taxIncluded(price) {
  const tax = Math.floor(price * 0.1);
  return price + tax;             // Kirim hasil perhitungan kembali ke pemanggil
}

// Panggil function yang sama dengan harga satuan berbeda
console.log(taxIncluded(1200));   // 1320
console.log(taxIncluded(980));    // 1078

// Kalau value lupa dioper, price berisi undefined
console.log(taxIncluded());       // NaN
Tiga Cara Memanggil Function yang Sama
DefinisitaxIncluded(price)taxIncluded(1200)taxIncluded(980)taxIncluded()price = 1200tax = 120price = 980tax = 98price = undefinedtax = NaNMengembalikan 1320Mengembalikan 1078Mengembalikan NaNmengoper valuemengoper valuetanpa value
Kalau value yang masuk ke price berubah, value yang dikembalikan juga berubah. Pada pemanggilan tanpa value, price menjadi undefined dan hasilnya NaN.

Yang masuk ke price hanyalah value-nya, jadi mau kamu tulis 1200 langsung atau kamu oper lewat variabel seperti itemPrice, cara kerja function-nya tetap sama.

Tampilkan durasi pelatihan dalam bentuk "X jam Y menit". lectureMinutes dan practiceMinutes sudah dideklarasikan.

① Deklarasikan function yang menerima jumlah menit dan mengembalikan string berbentuk "X jam Y menit".

② Tampilkan durasi materi sebagai "Materi: X jam Y menit".

③ Tampilkan durasi praktik sebagai "Praktik: X jam Y menit".

④ Tampilkan gabungan keduanya sebagai "Total: X jam Y menit".

(Kalau berjalan dengan benar, penjelasan akan muncul.)

JavaScript / TypeScript Editor

Jalankan kode untuk melihat output

Menerima Beberapa Argument — Dicocokkan Berdasarkan Posisi

Kalau persentase diskon berbeda untuk tiap level member atau tiap promo, function yang hanya menerima harga satuan tidak cukup. Kalau pemanggil bisa ikut mengoper persentase diskonnya, perhitungannya tetap ada di satu tempat dan hanya persentasenya yang ditentukan oleh pemanggil.

Parameter dipisahkan dengan koma. Value dari pemanggil dicocokkan sesuai urutan penulisannya: value pertama masuk ke parameter pertama, value kedua ke parameter kedua. Pencocokannya tidak berdasarkan nama, jadi kalau urutannya tertukar pun kodenya tetap valid secara sintaks.

// Terima harga satuan dan persentase diskon, lalu kembalikan harga setelah diskon
function applyDiscount(price, rate) {
  return Math.floor(price * (1 - rate));
}

// Value pertama masuk ke price, value kedua ke rate
console.log(applyDiscount(2400, 0.2));    // 1920
console.log(applyDiscount(2400, 0.05));   // 2280

// Walaupun urutannya tertukar, perhitungannya tetap berjalan
console.log(applyDiscount(0.2, 2400));    // -480
Argument Dicocokkan Berdasarkan Posisi
Oper(2400, 0.2)price = 2400rate = 0.2Hitung2400 × 0.8Mengembalikan 1920Oper(0.2, 2400)price = 0.2rate = 2400Hitung0.2 × -2399Mengembalikan -480
Dua value yang sama dioper ke applyDiscount, hanya urutannya yang ditukar. Menukar urutan tidak memunculkan error; hanya hasil perhitungannya yang berubah.

Baris pemanggilan hanya berisi value, jadi dengan membaca applyDiscount(0.2, 2400) saja kamu tidak akan sadar ada yang tertukar. Kalau yang kembali adalah value yang mustahil seperti -480, bandingkan urutan value di pemanggilan dengan definisi function-nya.

Hitung jumlah yang harus dibayar untuk sebuah pesanan dengan dua function. unitPrice, quantity, shippingFee, dan couponAmount sudah dideklarasikan.

① Deklarasikan function yang menerima harga satuan dan jumlah barang, lalu mengembalikan subtotal.

② Deklarasikan function yang menerima subtotal, ongkos kirim, dan potongan harga (dengan urutan itu), lalu mengembalikan jumlah yang harus dibayar.

③ Oper return value dari ① ke ② dan tampilkan "Total bayar: X yen".

④ Ubah ongkos kirim menjadi 0 dan tampilkan "Jika gratis ongkir: X yen".

JavaScript / TypeScript Editor

Jalankan kode untuk melihat output

Memperlakukan Function sebagai Value — Function Expression dan Variabel

Rumus ongkos kirim untuk pengiriman reguler dan pengiriman kilat benar-benar berbeda. Daripada menulis pilihan mana yang dipakai di setiap pemanggilan, kamu bisa menyimpan function-nya sendiri di sebuah variabel, lalu pemanggil cukup memanggil variabel itu.

Function expression (cara menulis yang menyimpan function ke variabel sebagai value) adalah statement assignment yang ditulis const nama = function (parameter) { body };. function declaration sudah disiapkan sebelum kode dijalankan dari atas ke bawah, sedangkan variabel pada function expression baru menerima function-nya saat baris assignment itu dijalankan (mekanismenya dibahas di artikel tentang scope dan hoisting).

// function declaration bisa dipanggil bahkan dari baris sebelum deklarasinya
console.log(expressShipping(1.5));       // 900

function expressShipping(weight) {
  return weight <= 2 ? 900 : 1300;
}

// Function expression: simpan function ke variabel sebagai value
const normalShipping = function (weight) {
  return weight <= 2 ? 500 : 800;
};

// Tanpa tanda kurung, function itu sendiri yang masuk ke variabel lain
const feeRule = normalShipping;
console.log(feeRule(3));                 // 800
console.log(typeof feeRule);             // function
console.log(typeof normalShipping(3));   // number
Bisakah Dipanggil dari Baris Sebelumnya?
Dideklarasikandengan functionDipanggil sebelumbaris deklarasiSudah disiapkansebelum kode jalanMengembalikan 900Masuk variabellewat expressionDipanggil sebelumbaris assignmentVariabel belumberisi functionBerhenti denganReferenceError
Kalau dipanggil di baris sebelum assignment, eksekusi berhenti dengan ReferenceError. Function yang disimpan lewat function expression baru bisa dipanggil setelah baris assignment-nya dijalankan.

Pesan error lengkapnya adalah ReferenceError: Cannot access 'normalShipping' before initialization. Perhatikan juga baris feeRule pada kode di atas: kalau nama function di-assign tanpa tanda kurung, function itu sendiri yang masuk ke variabel lain.

Dengan dan Tanpa Tanda Kurung
feeRule =normalShippingFunction itusendiri masuktypeof-nyafunctionBisa dipanggilnanti: feeRule(3)feeRule =normalShipping(3)Body dijalankan,800 yang masuktypeof-nyanumberfeeRule(3) jadiTypeError
Tanpa tanda kurung, yang masuk ke variabel adalah function itu sendiri; dengan tanda kurung, yang masuk adalah hasil menjalankannya. Kalau function yang ingin dipanggil nanti kamu beri tanda kurung, yang tersisa hanya return value-nya.

Kalau Nama yang Sama Dideklarasikan Dua Kali, Body yang Terakhir yang Dipakai

Karena function declaration disiapkan sebelum kode dijalankan, kalau kamu mendeklarasikan dua function dengan nama yang sama, pemanggilan tepat di baris setelah deklarasi pertama pun akan menjalankan body yang ditulis belakangan. Eksekusinya tidak berhenti, jadi function bernama sama yang letaknya berjauhan sulit disadari. Dengan function expression const, deklarasi kedua menjadi SyntaxError dan kodenya tidak mulai dijalankan sama sekali.

Ubah cara menghitung biaya transaksi sesuai jenis member. amount dan isPremium sudah dideklarasikan.

① Tulis standardFee yang mengembalikan biaya 3% dan premiumFee yang mengembalikan biaya 1% sebagai function expression (bulatkan ke bawah).

② Pakai isPremium untuk memilih salah satunya dan simpan di applyFee.

③ Panggil applyFee dan tampilkan "Biaya: X yen".

④ Panggil standardFee secara langsung dan tampilkan "Untuk member reguler: X yen".

JavaScript / TypeScript Editor

Jalankan kode untuk melihat output

Apa yang Terjadi Tanpa Return Value — Lupa Menulis return

Kalau di dalam function kamu menulis console.log, teksnya muncul di layar saat function dipanggil. Karena ada yang tampil, function-nya terlihat bekerja, tapi kalau return value-nya kamu simpan di variabel lalu dipakai, string yang kamu harapkan tidak ada di sana.

return adalah statement yang mengembalikan value sekaligus menghentikan function di titik itu. Function tanpa return mengembalikan undefined — menampilkan sesuatu dan mengembalikan value adalah dua hal yang berbeda. console.log hanya menampilkan ke layar; tidak ada yang diserahkan ke pemanggil.

// Dengan return: teksnya kembali ke pemanggil
function formatLabel(name, stock) {
  return `${name} (sisa ${stock})`;
  console.log("Tidak terjangkau");   // Ada setelah return, jadi tidak pernah dijalankan
}

// Tanpa return: teksnya tampil, tapi return value-nya undefined
function printLabel(name, stock) {
  console.log(`${name} (sisa ${stock})`);
}

const label = formatLabel("Lampu Meja", 3);
console.log(label);      // Lampu Meja (sisa 3)

const printed = printLabel("USB Hub", 5);    // USB Hub (sisa 5)
console.log(printed);    // undefined
Cara function ditulisYang terjadi saat dipanggilYang diterima pemanggil
return sebuah teksTeksnya kembali ke pemanggilLampu Meja (sisa 3)
Hanya berisi console.logTampil di layar, tanpa returnundefined
console.log setelah returnBaris setelahnya tidak jalanTeksnya tetap kembali

Kalau value-nya akan dipakai oleh pemanggil, serahkan dengan return, bukan dengan menampilkannya.

Pindah Baris Setelah return Membuat Value Tidak Dikembalikan

Kalau kamu pindah baris tepat setelah return lalu menulis value-nya di baris berikutnya, JavaScript menganggap statement-nya berakhir di baris return, dan function mengembalikan undefined. Kesalahan ini mudah terjadi saat template literal yang panjang kamu pindahkan ke baris sendiri supaya lebih mudah dibaca. Selalu mulai menulis value-nya di baris yang sama dengan return.

Tambahkan ongkos kirim untuk mendapatkan total bayar. orderTotal, largeOrderTotal, dan shippingFee (function yang seharusnya mengembalikan ongkos kirim) sudah dideklarasikan.

① Tampilkan orderTotal ditambah ongkos kirim sebagai "Total bayar: X yen".

② Tampilkan largeOrderTotal dengan bentuk yang sama.

③ Deklarasikan shippingFeeFixed yang mengembalikan ongkos kirim sebagai angka untuk total berapa pun.

④ Tampilkan ulang total bayar ① dengan memakai shippingFeeFixed.

JavaScript / TypeScript Editor

Jalankan kode untuk melihat output
QUIZ

Cek Pemahaman

Jawab setiap pertanyaan satu per satu.

Soal 1Kalau kamu mendeklarasikan function double(n) { n * 2; } lalu menjalankan console.log(double(4));, apa yang ditampilkan?

Soal 2Kalau function fee(price, rate) { return price * rate; } dipanggil sebagai fee(0.2, 1000), apa yang masuk ke price?

Soal 3Apa yang terjadi kalau calc(1) dipanggil di baris sebelum assignment const calc = function (n) { return n + 1; };?