Dalam JavaScript, suatu fungsi bukanlah “struktur bahasa ajaib”, melainkan jenis nilai khusus.
Sintaks yang kita gunakan sebelumnya disebut Deklarasi Fungsi :
fungsi ucapkan Hai() { peringatan("Halo" ); }
Ada sintaks lain untuk membuat fungsi yang disebut Ekspresi Fungsi .
Ini memungkinkan kita membuat fungsi baru di tengah ekspresi apa pun.
Misalnya:
katakanlah Hai = fungsi() { peringatan("Halo" ); };
Di sini kita bisa melihat variabel sayHi
mendapatkan nilai, fungsi baru, dibuat sebagai function() { alert("Hello"); }
.
Karena pembuatan fungsi terjadi dalam konteks ekspresi penugasan (di sebelah kanan =
), ini adalah Function Expression .
Harap dicatat, tidak ada nama setelah kata kunci function
. Menghilangkan nama diperbolehkan untuk Ekspresi Fungsi.
Disini kita langsung menugaskannya ke variabel, jadi arti dari contoh kode ini sama: “buat fungsi dan masukkan ke dalam variabel sayHi
”.
Dalam situasi lebih lanjut, yang akan kita temui nanti, suatu fungsi dapat dibuat dan segera dipanggil atau dijadwalkan untuk dieksekusi nanti, tidak disimpan di mana pun, sehingga tetap anonim.
Mari kita tegaskan kembali: tidak peduli bagaimana suatu fungsi dibuat, suatu fungsi adalah sebuah nilai. Kedua contoh di atas menyimpan fungsi dalam variabel sayHi
.
Kita bahkan dapat mencetak nilai tersebut menggunakan alert
:
fungsi ucapkan Hai() { peringatan("Halo" ); } waspada(ucapkanHai); // menampilkan kode fungsi
Harap dicatat bahwa baris terakhir tidak menjalankan fungsi tersebut, karena tidak ada tanda kurung setelah sayHi
. Ada bahasa pemrograman di mana penyebutan nama fungsi menyebabkan eksekusinya, namun JavaScript tidak seperti itu.
Dalam JavaScript, fungsi adalah sebuah nilai, jadi kita bisa memperlakukannya sebagai sebuah nilai. Kode di atas menunjukkan representasi stringnya, yang merupakan kode sumber.
Tentu saja, suatu fungsi adalah nilai khusus, dalam artian kita dapat menyebutnya seperti sayHi()
.
Tapi itu tetap sebuah nilai. Jadi kita bisa mengolahnya seperti nilai-nilai lainnya.
Kita dapat menyalin suatu fungsi ke variabel lain:
fungsi sayHi() { // (1) buat peringatan("Halo" ); } biarkan func = sayHi; // (2) salin fungsi(); // Halo // (3) jalankan penyalinannya (berhasil)! sayHai(); // Halo // ini masih berfungsi juga (kenapa tidak)
Inilah yang terjadi di atas secara detail:
Deklarasi Fungsi (1)
membuat fungsi dan memasukkannya ke dalam variabel bernama sayHi
.
Baris (2)
menyalinnya ke dalam variabel func
. Harap dicatat lagi: tidak ada tanda kurung setelah sayHi
. Jika ada, maka func = sayHi()
akan menulis hasil panggilan sayHi()
ke dalam func
, bukan fungsi sayHi
itu sendiri.
Sekarang fungsinya dapat dipanggil sebagai sayHi()
dan func()
.
Kita juga bisa menggunakan Ekspresi Fungsi untuk mendeklarasikan sayHi
, pada baris pertama:
misalkan sayHi = function() { // (1) buat peringatan("Halo" ); }; biarkan func = sayHi; // ...
Semuanya akan bekerja sama.
Mengapa ada titik koma di akhir?
Anda mungkin bertanya-tanya, mengapa Ekspresi Fungsi memiliki titik koma ;
di bagian akhir, namun Deklarasi Fungsi tidak:
fungsi ucapkan Hai() { // ... } katakanlah Hai = fungsi() { // ... };
Jawabannya sederhana: Ekspresi Fungsi dibuat di sini sebagai function(…) {…}
di dalam pernyataan penugasan: let sayHi = …;
. Titik koma ;
direkomendasikan di akhir pernyataan, itu bukan bagian dari sintaks fungsi.
Titik koma akan digunakan untuk tugas yang lebih sederhana, seperti let sayHi = 5;
, dan itu juga ada untuk penetapan fungsi.
Mari kita lihat lebih banyak contoh meneruskan fungsi sebagai nilai dan menggunakan ekspresi fungsi.
Kami akan menulis fungsi ask(question, yes, no)
dengan tiga parameter:
question
Teks pertanyaan
yes
Fungsi untuk dijalankan jika jawabannya “Ya”
no
Fungsi untuk dijalankan jika jawabannya “Tidak”
Fungsi tersebut harus menanyakan question
dan, bergantung pada jawaban pengguna, memanggil yes()
atau no()
:
fungsi bertanya(pertanyaan, ya, tidak) { jika (konfirmasi(pertanyaan)) ya() kalau tidak, tidak(); } fungsi tampilkan Oke() { alert("Anda setuju."); } fungsi tampilkanBatal() { alert("Anda membatalkan eksekusi." ); } // penggunaan: fungsi showOk, showCancel diteruskan sebagai argumen untuk ditanyakan bertanya("Apakah Anda setuju?", tampilkan Oke, tampilkan Batal);
Dalam praktiknya, fungsi-fungsi tersebut cukup berguna. Perbedaan utama antara ask
di kehidupan nyata dan contoh di atas adalah bahwa fungsi kehidupan nyata menggunakan cara yang lebih kompleks untuk berinteraksi dengan pengguna daripada confirm
sederhana. Di browser, fungsi seperti itu biasanya menampilkan jendela pertanyaan yang tampak bagus. Tapi itu cerita lain.
Argumen showOk
dan showCancel
dari ask
disebut fungsi callback atau hanya callbacks .
Idenya adalah kita meneruskan suatu fungsi dan mengharapkannya untuk “dipanggil kembali” nanti jika perlu. Dalam kasus kami, showOk
menjadi panggilan balik untuk jawaban “ya”, dan showCancel
untuk jawaban “tidak”.
Kita dapat menggunakan Ekspresi Fungsi untuk menulis fungsi yang setara dan lebih pendek:
fungsi bertanya(pertanyaan, ya, tidak) { jika (konfirmasi(pertanyaan)) ya() kalau tidak, tidak(); } bertanya( "Apakah kamu setuju?", function() { alert("Anda setuju."); }, function() { alert("Anda membatalkan eksekusi."); } );
Di sini, fungsi dideklarasikan tepat di dalam panggilan ask(...)
. Mereka tidak punya nama, sehingga disebut anonim . Fungsi seperti itu tidak dapat diakses di luar ask
(karena tidak ditugaskan ke variabel), tapi itulah yang kita inginkan di sini.
Kode seperti itu muncul di skrip kami dengan sangat alami, sesuai dengan semangat JavaScript.
Fungsi adalah nilai yang mewakili “tindakan”
Nilai reguler seperti string atau angka mewakili data .
Suatu fungsi dapat dianggap sebagai suatu tindakan .
Kita bisa meneruskannya antar variabel dan menjalankannya kapan pun kita mau.
Mari kita rumuskan perbedaan utama antara Deklarasi Fungsi dan Ekspresi.
Pertama, sintaksisnya: cara membedakannya dalam kode.
Deklarasi Fungsi: suatu fungsi, yang dideklarasikan sebagai pernyataan terpisah, dalam aliran kode utama:
// Deklarasi Fungsi fungsi jumlah(a, b) { kembalikan a+b; }
Ekspresi Fungsi: suatu fungsi, dibuat di dalam ekspresi atau di dalam konstruksi sintaksis lainnya. Di sini, fungsi dibuat di sisi kanan “ekspresi penugasan” =
:
// Ekspresi Fungsi misalkan jumlah = fungsi(a, b) { kembalikan a+b; };
Perbedaan yang lebih halus adalah ketika suatu fungsi dibuat oleh mesin JavaScript.
Ekspresi Fungsi dibuat ketika eksekusi mencapainya dan hanya dapat digunakan sejak saat itu.
Setelah alur eksekusi berpindah ke sisi kanan penugasan let sum = function…
– ini dia, fungsi dibuat dan dapat digunakan (ditugaskan, dipanggil, dll.) mulai sekarang.
Deklarasi Fungsi berbeda.
Deklarasi Fungsi dapat dipanggil lebih awal dari yang ditentukan.
Misalnya, Deklarasi Fungsi global terlihat di seluruh skrip, di mana pun lokasinya.
Itu karena algoritma internal. Saat JavaScript bersiap untuk menjalankan skrip, pertama-tama JavaScript akan mencari Deklarasi Fungsi global di dalamnya dan membuat fungsinya. Kita dapat menganggapnya sebagai “tahap inisialisasi”.
Dan setelah semua Deklarasi Fungsi diproses, kode tersebut dieksekusi. Jadi ia memiliki akses ke fungsi-fungsi ini.
Misalnya, ini berfungsi:
sayHi("Yohanes"); // Halo, John fungsi sayHi(nama) { peringatan( `Halo, ${nama}` ); }
Deklarasi Fungsi sayHi
dibuat saat JavaScript bersiap untuk memulai skrip dan terlihat di mana pun di dalamnya.
…Jika itu adalah Ekspresi Fungsi, maka itu tidak akan berfungsi:
sayHi("Yohanes"); // kesalahan! misalkan sayHi = function(name) { // (*) tidak ada keajaiban lagi peringatan( `Halo, ${nama}` ); };
Ekspresi Fungsi dibuat ketika eksekusi mencapainya. Itu hanya akan terjadi di baris (*)
. Terlambat.
Fitur khusus lainnya dari Deklarasi Fungsi adalah cakupan bloknya.
Dalam mode ketat, ketika Deklarasi Fungsi berada dalam blok kode, Deklarasi Fungsi akan terlihat di mana saja di dalam blok tersebut. Tapi tidak di luar itu.
Sebagai contoh, bayangkan kita perlu mendeklarasikan sebuah fungsi welcome()
bergantung pada variabel age
yang kita dapatkan saat runtime. Dan kemudian kami berencana untuk menggunakannya beberapa waktu kemudian.
Jika kita menggunakan Deklarasi Fungsi, itu tidak akan berfungsi sebagaimana mestinya:
let age = prompt("Berapa umur anda?", 18); // mendeklarasikan suatu fungsi secara kondisional jika (umur < 18) { fungsi selamat datang() { peringatan("Halo!"); } } kalau tidak { fungsi selamat datang() { alert("Salam!"); } } // ...gunakan nanti selamat datang(); // Kesalahan: selamat datang tidak ditentukan
Itu karena Deklarasi Fungsi hanya terlihat di dalam blok kode tempatnya berada.
Berikut contoh lainnya:
misalkan umur = 16; // ambil 16 sebagai contoh jika (umur < 18) { selamat datang(); // (berjalan) // | fungsi selamat datang() { // | peringatan("Halo!"); // | Deklarasi Fungsi tersedia } // | di mana pun di blok tempat deklarasinya // | selamat datang(); // / (berjalan) } kalau tidak { fungsi selamat datang() { alert("Salam!"); } } // Di sini kita kehabisan kurung kurawal, // jadi kita tidak bisa melihat Deklarasi Fungsi yang dibuat di dalamnya. selamat datang(); // Kesalahan: selamat datang tidak ditentukan
Apa yang bisa kita lakukan agar welcome
terlihat di luar if
?
Pendekatan yang benar adalah dengan menggunakan Ekspresi Fungsi dan menetapkan welcome
ke variabel yang dideklarasikan di luar if
dan memiliki visibilitas yang tepat.
Kode ini berfungsi sebagaimana mestinya:
let age = prompt("Berapa umur anda?", 18); biarkan selamat datang; jika (umur < 18) { selamat datang = fungsi() { peringatan("Halo!"); }; } kalau tidak { selamat datang = fungsi() { alert("Salam!"); }; } selamat datang(); // oke sekarang
Atau kita bisa menyederhanakannya lebih jauh lagi dengan menggunakan operator tanda tanya ?
:
let age = prompt("Berapa umur anda?", 18); biarkan selamat datang = (umur < 18) ? function() { peringatan("Halo!"); } : function() { peringatan("Salam!"); }; selamat datang(); // oke sekarang
Kapan memilih Deklarasi Fungsi versus Ekspresi Fungsi?
Sebagai aturan praktis, ketika kita perlu mendeklarasikan suatu fungsi, hal pertama yang harus dipertimbangkan adalah sintaksis Deklarasi Fungsi. Ini memberikan lebih banyak kebebasan dalam mengatur kode kita, karena kita dapat memanggil fungsi tersebut sebelum dideklarasikan.
Itu juga lebih baik agar mudah dibaca, karena lebih mudah untuk mencari function f(…) {…}
dalam kode daripada let f = function(…) {…};
. Deklarasi Fungsi lebih “eye-catching”.
…Tetapi jika Deklarasi Fungsi tidak cocok untuk kita karena alasan tertentu, atau kita memerlukan deklarasi bersyarat (kita baru saja melihat contohnya), maka Ekspresi Fungsi harus digunakan.
Fungsi adalah nilai. Mereka dapat ditetapkan, disalin, atau dideklarasikan di mana saja dalam kode.
Jika fungsi dideklarasikan sebagai pernyataan terpisah dalam alur kode utama, hal itu disebut “Deklarasi Fungsi”.
Jika fungsi dibuat sebagai bagian dari ekspresi, itu disebut “Ekspresi Fungsi”.
Deklarasi Fungsi diproses sebelum blok kode dieksekusi. Mereka terlihat di mana-mana di blok tersebut.
Ekspresi Fungsi dibuat ketika aliran eksekusi mencapainya.
Dalam kebanyakan kasus ketika kita perlu mendeklarasikan suatu fungsi, Deklarasi Fungsi lebih disukai, karena dapat dilihat sebelum deklarasi itu sendiri. Hal ini memberi kita lebih banyak fleksibilitas dalam pengorganisasian kode, dan biasanya lebih mudah dibaca.
Jadi kita harus menggunakan Ekspresi Fungsi hanya ketika Deklarasi Fungsi tidak sesuai untuk tugas tersebut. Kita telah melihat beberapa contohnya dalam bab ini, dan akan melihat lebih banyak lagi di masa mendatang.