Seringkali kita perlu melakukan tindakan serupa di banyak tempat dalam skrip.
Misalnya, kita perlu menampilkan pesan yang terlihat bagus ketika pengunjung login, logout, dan mungkin di tempat lain.
Fungsi adalah “blok penyusun” utama program. Mereka mengizinkan kode dipanggil berkali-kali tanpa pengulangan.
Kita telah melihat contoh fungsi bawaan, seperti alert(message)
, prompt(message, default)
dan confirm(question)
. Tapi kita juga bisa membuat fungsinya sendiri.
Untuk membuat suatu fungsi kita dapat menggunakan deklarasi fungsi .
Ini terlihat seperti ini:
fungsi tampilkanPesan() { alert('Halo semuanya!' ); }
Kata kunci function
didahulukan, lalu nama fungsinya , lalu daftar parameter di antara tanda kurung (dipisahkan koma, kosongkan pada contoh di atas, kita akan lihat contohnya nanti) dan terakhir kode fungsinya, juga diberi nama “badan fungsi”, di antara kurung kurawal.
nama fungsi(parameter1, parameter2, ... parameterN) { // tubuh }
Fungsi baru kita dapat dipanggil dengan namanya: showMessage()
.
Misalnya:
fungsi tampilkanPesan() { alert('Halo semuanya!' ); } tampilkanPesan(); tampilkanPesan();
Panggilan showMessage()
mengeksekusi kode fungsi. Di sini kita akan melihat pesan itu dua kali.
Contoh ini dengan jelas menunjukkan salah satu tujuan utama fungsi: untuk menghindari duplikasi kode.
Jika kita perlu mengubah pesan atau cara menampilkannya, cukup dengan memodifikasi kode di satu tempat: fungsi yang mengeluarkannya.
Variabel yang dideklarasikan di dalam suatu fungsi hanya terlihat di dalam fungsi tersebut.
Misalnya:
fungsi tampilkanPesan() { let message = "Halo, saya JavaScript!"; // variabel lokal peringatan( pesan ); } tampilkanPesan(); // Halo, saya JavaScript! peringatan( pesan ); // <-- Kesalahan! Variabelnya bersifat lokal terhadap fungsi tersebut
Suatu fungsi juga dapat mengakses variabel luar, misalnya:
biarkan namapengguna = 'John'; fungsi tampilkanPesan() { biarkan pesan = 'Halo, ' + Nama Pengguna; peringatan (pesan); } tampilkanPesan(); // Halo, John
Fungsi ini memiliki akses penuh ke variabel luar. Itu juga dapat memodifikasinya.
Misalnya:
biarkan namapengguna = 'John'; fungsi tampilkanPesan() { nama pengguna = "Bob"; // (1) mengubah variabel luar biarkan pesan = 'Halo, ' + nama pengguna; peringatan (pesan); } peringatan(Nama Pengguna); // John sebelum pemanggilan fungsi tampilkanPesan(); peringatan(Nama Pengguna); // Bob, nilainya diubah oleh fungsi
Variabel luar hanya digunakan jika tidak ada variabel lokal.
Jika variabel dengan nama yang sama dideklarasikan di dalam fungsi, maka variabel tersebut akan membayangi variabel luar. Misalnya, pada kode di bawah, fungsinya menggunakan userName
lokal. Yang luar diabaikan:
biarkan namapengguna = 'John'; fungsi tampilkanPesan() { biarkan namapengguna = "Bob"; // mendeklarasikan variabel lokal biarkan pesan = 'Halo, ' + nama pengguna; // Bob peringatan (pesan); } // fungsi akan membuat dan menggunakan nama penggunanya sendiri tampilkanPesan(); peringatan(Nama Pengguna); // John, tidak berubah, fungsi tidak mengakses variabel luar
Variabel global
Variabel yang dideklarasikan di luar fungsi apa pun, seperti userName
luar pada kode di atas, disebut global .
Variabel global terlihat dari fungsi apa pun (kecuali dibayangi oleh fungsi lokal).
Merupakan praktik yang baik untuk meminimalkan penggunaan variabel global. Kode modern memiliki sedikit atau tidak ada global. Sebagian besar variabel berada dalam fungsinya. Namun terkadang, mereka berguna untuk menyimpan data tingkat proyek.
Kita dapat meneruskan data sembarang ke fungsi menggunakan parameter.
Pada contoh di bawah, fungsi memiliki dua parameter: from
dan text
.
function showMessage(dari, teks) { // parameter: dari, teks peringatan(dari + ': ' + teks); } showMessage('Ann', 'Halo!'); // Ann: Halo! (*) showMessage('An', "Ada apa?"); // Ann: Ada apa? (**)
Saat fungsi dipanggil di baris (*)
dan (**)
, nilai yang diberikan disalin ke variabel lokal from
dan text
. Kemudian fungsinya menggunakannya.
Berikut satu contoh lagi: kita memiliki variabel from
dan meneruskannya ke fungsi. Harap dicatat: fungsinya berubah from
, tetapi perubahannya tidak terlihat di luar, karena suatu fungsi selalu mendapat salinan nilainya:
fungsi showMessage(dari, teks) { dari = '*' + dari + '*'; // membuat "dari" terlihat lebih bagus peringatan(dari + ':' + teks ); } biarkan dari = "Ann"; showMessage(dari, "Halo"); // *An*: Halo // nilai "dari" sama, fungsinya mengubah salinan lokal peringatan( dari ); // Ann
Ketika suatu nilai dilewatkan sebagai parameter fungsi, itu juga disebut argumen .
Dengan kata lain, untuk meluruskan istilah-istilah ini:
Parameter adalah variabel yang tercantum di dalam tanda kurung pada deklarasi fungsi (ini merupakan istilah waktu deklarasi).
Argumen adalah nilai yang diteruskan ke fungsi saat dipanggil (istilah waktu panggilan).
Kita mendeklarasikan fungsi yang mencantumkan parameternya, lalu memanggilnya argumen yang lewat.
Pada contoh di atas, kita mungkin mengatakan: “fungsi showMessage
dideklarasikan dengan dua parameter, kemudian dipanggil dengan dua argumen: from
dan "Hello"
”.
Jika suatu fungsi dipanggil, tetapi argumen tidak diberikan, maka nilai yang bersangkutan menjadi undefined
.
Misalnya, fungsi showMessage(from, text)
yang disebutkan di atas dapat dipanggil dengan satu argumen:
showMessage("Ann");
Itu bukan sebuah kesalahan. Panggilan seperti itu akan menghasilkan "*Ann*: undefined"
. Karena nilai text
tidak diteruskan, nilai tersebut menjadi undefined
.
Kita dapat menentukan apa yang disebut nilai “default” (untuk digunakan jika dihilangkan) untuk parameter dalam deklarasi fungsi, menggunakan =
:
function showMessage(dari, teks = "tidak ada teks yang diberikan") { peringatan(dari + ": " + teks ); } showMessage("Ann"); // Ann: tidak ada teks yang diberikan
Sekarang jika parameter text
tidak dilewatkan, maka akan mendapat nilai "no text given"
.
Nilai defaultnya juga masuk jika parameternya ada, tetapi sama persis dengan undefined
, seperti ini:
showMessage("Ann", tidak terdefinisi); // Ann: tidak ada teks yang diberikan
Di sini "no text given"
adalah string, tetapi bisa berupa ekspresi yang lebih kompleks, yang hanya dievaluasi dan ditetapkan jika parameternya hilang. Jadi, ini juga mungkin:
fungsi showMessage(dari, teks = fungsi lain()) { // anotherFunction() hanya dieksekusi jika tidak ada teks yang diberikan // hasilnya menjadi nilai teks }
Evaluasi parameter default
Dalam JavaScript, parameter default dievaluasi setiap kali fungsi dipanggil tanpa parameter terkait.
Pada contoh di atas, anotherFunction()
tidak dipanggil sama sekali, jika parameter text
disediakan.
Di sisi lain, ini dipanggil secara independen setiap kali ada text
yang hilang.
Parameter default dalam kode JavaScript lama
Beberapa tahun yang lalu, JavaScript tidak mendukung sintaks untuk parameter default. Jadi orang menggunakan cara lain untuk menentukannya.
Saat ini, kita dapat menemukannya dalam skrip lama.
Misalnya, pemeriksaan eksplisit untuk undefined
:
fungsi showMessage(dari, teks) { if (teks === tidak terdefinisi) { text = 'tidak ada teks yang diberikan'; } peringatan(dari + ": " + teks ); }
…Atau menggunakan ||
operator:
fungsi showMessage(dari, teks) { // Jika nilai teks salah, tetapkan nilai default // ini mengasumsikan bahwa text == "" sama dengan tidak ada teks sama sekali teks = teks || 'tidak ada teks yang diberikan'; ... }
Terkadang masuk akal untuk menetapkan nilai default untuk parameter pada tahap selanjutnya setelah deklarasi fungsi.
Kita dapat memeriksa apakah parameter dilewatkan selama eksekusi fungsi, dengan membandingkannya dengan undefined
:
fungsi tampilkanPesan(teks) { // ... if (teks === tidak terdefinisi) { // jika parameter tidak ada text = 'pesan kosong'; } peringatan(teks); } tampilkanPesan(); // pesan kosong
…Atau kita bisa menggunakan ||
operator:
fungsi tampilkanPesan(teks) { // jika teks tidak terdefinisi atau salah, setel ke 'kosong' teks = teks || 'kosong'; ... }
Mesin JavaScript modern mendukung operator penggabungan nol ??
, akan lebih baik jika sebagian besar nilai palsu, seperti 0
, dianggap “normal”:
fungsi showCount(hitungan) { // jika hitungan tidak ditentukan atau nol, tampilkan "tidak diketahui" alert(hitung ?? "tidak diketahui"); } showCount(0); // 0 showCount(nol); // tidak dikenal showCount(); // tidak dikenal
Suatu fungsi dapat mengembalikan nilai ke dalam kode panggilan sebagai hasilnya.
Contoh paling sederhana adalah fungsi yang menjumlahkan dua nilai:
fungsi jumlah(a, b) { kembalikan a+b; } misalkan hasil = jumlah(1, 2); peringatan(hasil); // 3
return
arahan dapat berada di mana saja pada fungsi tersebut. Ketika eksekusi mencapainya, fungsi berhenti, dan nilai dikembalikan ke kode panggilan (ditugaskan ke result
di atas).
Mungkin ada banyak kemunculan return
dalam satu fungsi. Misalnya:
fungsi pemeriksaanUmur(umur) { jika (umur >= 18) { kembali benar; } kalau tidak { return konfirmasi('Apakah kamu mempunyai izin dari orang tuamu?'); } } let age = prompt('Berapa umurmu?', 18); jika ( periksaUmur(umur) ) { alert('Akses diberikan'); } kalau tidak { alert('Akses ditolak'); }
Dimungkinkan untuk menggunakan return
tanpa nilai. Itu menyebabkan fungsi tersebut segera keluar.
Misalnya:
fungsi showMovie(usia) { jika ( !checkAge(usia) ) { kembali; } alert("Menampilkan filmnya"); // (*) // ... }
Pada kode di atas, jika checkAge(age)
mengembalikan false
, maka showMovie
tidak akan melanjutkan ke alert
.
Fungsi dengan return
kosong atau tanpa pengembalian undefined
Jika suatu fungsi tidak mengembalikan suatu nilai, maka sama saja dengan mengembalikan undefined
:
fungsi tidak melakukan apa-apa() { /* kosong */ } waspada( tidak melakukan apa-apa() === tidak terdefinisi ); // BENAR
return
kosong juga sama dengan return undefined
:
fungsi tidak melakukan apa-apa() { kembali; } waspada( tidak melakukan apa-apa() === tidak terdefinisi ); // BENAR
Jangan pernah menambahkan baris baru antara return
dan nilainya
Untuk ekspresi panjang return
, mungkin tergoda untuk meletakkannya di baris terpisah, seperti ini:
kembali (beberapa + panjang + ekspresi + atau + apa pun * f(a) + f(b))
Itu tidak berhasil, karena JavaScript menggunakan titik koma setelah return
. Itu akan bekerja sama seperti:
kembali; (beberapa + panjang + ekspresi + atau + apa pun * f(a) + f(b))
Jadi, ini secara efektif menjadi keuntungan kosong.
Jika kita ingin ekspresi yang dikembalikan terbungkus dalam beberapa baris, kita harus memulainya pada baris yang sama dengan return
. Atau setidaknya letakkan tanda kurung pembuka di sana sebagai berikut:
kembali ( beberapa + panjang + ekspresi + atau + terserah * f(a) + f(b) )
Dan itu akan berhasil seperti yang kita harapkan.
Fungsi adalah tindakan. Jadi nama mereka biasanya berupa kata kerja. Kode tersebut harus singkat, seakurat mungkin, dan menjelaskan fungsi fungsi tersebut, sehingga seseorang yang membaca kode mendapatkan indikasi tentang fungsi fungsi tersebut.
Merupakan praktik yang tersebar luas untuk memulai suatu fungsi dengan awalan verbal yang secara samar-samar menggambarkan tindakan tersebut. Harus ada kesepakatan dalam tim mengenai arti awalan.
Misalnya, fungsi yang dimulai dengan "show"
biasanya menampilkan sesuatu.
Fungsi dimulai dengan…
"get…"
– mengembalikan nilai,
"calc…"
– menghitung sesuatu,
"create…"
– buat sesuatu,
"check…"
– memeriksa sesuatu dan mengembalikan boolean, dll.
Contoh nama tersebut:
showMessage(..) // menampilkan pesan getAge(..) // mengembalikan usia (entah bagaimana mendapatkannya) calcSum(..) // menghitung jumlah dan mengembalikan hasilnya createForm(..) // membuat formulir (dan biasanya mengembalikannya) checkPermission(..) // memeriksa izin, mengembalikan nilai benar/salah
Dengan adanya awalan, sekilas nama fungsi memberikan pemahaman tentang jenis pekerjaan yang dilakukannya dan jenis nilai yang dikembalikannya.
Satu fungsi – satu tindakan
Suatu fungsi harus melakukan apa yang disarankan oleh namanya, tidak lebih.
Dua tindakan independen biasanya memerlukan dua fungsi, meskipun keduanya biasanya dipanggil bersama (dalam hal ini kita dapat membuat fungsi ke-3 yang memanggil keduanya).
Beberapa contoh pelanggaran aturan ini:
getAge
– akan buruk jika menampilkan alert
seiring bertambahnya usia (seharusnya hanya didapat).
createForm
– akan buruk jika memodifikasi dokumen, menambahkan formulir ke dalamnya (hanya harus membuat dan mengembalikannya).
checkPermission
– akan buruk jika menampilkan pesan access granted/denied
(seharusnya hanya melakukan pemeriksaan dan mengembalikan hasilnya).
Contoh-contoh ini mengasumsikan arti umum dari awalan. Anda dan tim bebas menyepakati arti lain, namun biasanya tidak jauh berbeda. Bagaimanapun, Anda harus memiliki pemahaman yang kuat tentang arti awalan, apa yang bisa dan tidak bisa dilakukan oleh fungsi awalan. Semua fungsi dengan awalan yang sama harus mematuhi aturan. Dan tim harus berbagi pengetahuan.
Nama fungsi ultrapendek
Fungsi yang sering digunakan terkadang memiliki nama yang sangat pendek.
Misalnya, kerangka jQuery mendefinisikan suatu fungsi dengan $
. Pustaka Lodash memiliki fungsi intinya bernama _
.
Ini adalah pengecualian. Umumnya nama fungsi harus ringkas dan deskriptif.
Fungsinya harus singkat dan melakukan satu hal saja. Jika fungsinya besar, mungkin ada baiknya membagi fungsi tersebut menjadi beberapa fungsi yang lebih kecil. Terkadang mengikuti aturan ini mungkin tidak semudah itu, tapi ini jelas merupakan hal yang baik.
Fungsi terpisah tidak hanya lebih mudah untuk diuji dan di-debug – keberadaannya merupakan komentar yang bagus!
Misalnya, bandingkan dua fungsi showPrimes(n)
di bawah ini. Masing-masing menghasilkan bilangan prima hingga n
.
Varian pertama menggunakan label:
fungsi tampilkan bilangan prima(n) { nextPrime: for (misalkan i = 2; i < n; i++) { untuk (misalkan j = 2; j < i; j++) { jika (i % j == 0) lanjutkan nextPrime; } peringatan( saya ); // bilangan prima } }
Varian kedua menggunakan fungsi tambahan isPrime(n)
untuk menguji primalitas:
fungsi tampilkan bilangan prima(n) { untuk (misalkan i = 2; i < n; i++) { jika (!isPrime(i)) lanjutkan; peringatan(i); // bilangan prima } } fungsi adalahPrime(n) { untuk (misalkan i = 2; i < n; i++) { jika ( n % i == 0) mengembalikan salah; } kembali benar; }
Varian kedua lebih mudah dipahami bukan? Alih-alih potongan kode, kita melihat nama tindakan ( isPrime
). Terkadang orang menyebut kode seperti self-describing .
Jadi, fungsi dapat dibuat meskipun kita tidak bermaksud menggunakannya kembali. Mereka menyusun kode dan membuatnya dapat dibaca.
Deklarasi fungsi terlihat seperti ini:
nama fungsi(parameter, dibatasi, dengan, koma) { /* kode */ }
Nilai yang diteruskan ke suatu fungsi sebagai parameter disalin ke variabel lokalnya.
Suatu fungsi dapat mengakses variabel luar. Tapi itu hanya berfungsi dari dalam ke luar. Kode di luar fungsi tidak melihat variabel lokalnya.
Suatu fungsi dapat mengembalikan suatu nilai. Jika tidak, maka hasilnya adalah undefined
.
Agar kodenya bersih dan mudah dipahami, disarankan untuk menggunakan variabel dan parameter lokal saja dalam fungsi, bukan variabel luar.
Selalu lebih mudah untuk memahami fungsi yang mendapatkan parameter, bekerja dengannya, dan mengembalikan hasil daripada fungsi yang tidak mendapatkan parameter, namun memodifikasi variabel luar sebagai efek samping.
Penamaan fungsi:
Sebuah nama harus dengan jelas menjelaskan fungsi fungsinya. Saat kita melihat pemanggilan fungsi dalam kode, nama yang bagus langsung memberi kita pemahaman tentang apa yang dilakukan dan dikembalikannya.
Fungsi adalah suatu tindakan, jadi nama fungsi biasanya berbentuk verbal.
Ada banyak awalan fungsi terkenal seperti create…
, show…
, get…
, check…
dan seterusnya. Gunakan mereka untuk memberi petunjuk tentang fungsi suatu fungsi.
Fungsi adalah elemen penyusun utama skrip. Sekarang kita telah membahas dasar-dasarnya, sehingga kita dapat mulai membuat dan menggunakannya. Tapi itu hanya permulaan dari jalannya. Kami akan kembali membahasnya berkali-kali, mempelajari lebih dalam fitur-fitur lanjutannya.
pentingnya: 4
Fungsi berikut mengembalikan true
jika parameter age
lebih besar dari 18
.
Jika tidak, ia akan meminta konfirmasi dan mengembalikan hasilnya:
fungsi pemeriksaanUmur(umur) { jika (umur > 18) { kembali benar; } kalau tidak { // ... return konfirmasi('Apakah orang tua mengizinkanmu?'); } }
Apakah fungsinya akan bekerja secara berbeda jika else
dihapus?
fungsi pemeriksaanUmur(umur) { jika (umur > 18) { kembali benar; } // ... return konfirmasi('Apakah orang tua mengizinkanmu?'); }
Apakah ada perbedaan perilaku kedua varian ini?
Tidak ada bedanya!
Dalam kedua kasus tersebut, return confirm('Did parents allow you?')
dijalankan tepat ketika kondisi if
salah.
pentingnya: 4
Fungsi berikut mengembalikan true
jika parameter age
lebih besar dari 18
.
Jika tidak, ia akan meminta konfirmasi dan mengembalikan hasilnya.
fungsi pemeriksaanUmur(umur) { jika (umur > 18) { kembali benar; } kalau tidak { return konfirmasi('Apakah orang tua mengizinkanmu?'); } }
Tulis ulang, untuk melakukan hal yang sama, tetapi tanpa if
, dalam satu baris.
Buat dua varian checkAge
:
Menggunakan operator tanda tanya ?
Menggunakan ATAU ||
Menggunakan operator tanda tanya '?'
:
fungsi pemeriksaanUmur(umur) { kembali (usia > 18) ? true : konfirmasi('Apakah orang tua mengizinkanmu?'); }
Menggunakan ATAU ||
(varian terpendek):
fungsi pemeriksaanUmur(umur) { kembali (usia > 18) || konfirmasi('Apakah orang tua mengizinkanmu?'); }
Perhatikan bahwa tanda kurung sekitar age > 18
tidak diperlukan di sini. Mereka ada untuk keterbacaan yang lebih baik.
pentingnya: 1
Tulis fungsi min(a,b)
yang mengembalikan bilangan terkecil dari dua bilangan a
dan b
.
Misalnya:
menit(2, 5) == 2 menit(3, -1) == -1 menit(1, 1) == 1
Solusi menggunakan if
:
fungsi min(a, b) { jika (a < b) { kembalikan a; } kalau tidak { kembali b; } }
Solusi dengan operator tanda tanya '?'
:
fungsi min(a, b) { kembalikan a < b ? a : b; }
PS Dalam kasus persamaan a == b
tidak masalah apa yang dikembalikan.
pentingnya: 4
Tulis fungsi pow(x,n)
yang mengembalikan x
dalam pangkat n
. Atau, dengan kata lain, mengalikan x
dengan dirinya sendiri n
kali dan mengembalikan hasilnya.
kekuatan(3, 2) = 3 * 3 = 9 kekuatan(3, 3) = 3 * 3 * 3 = 27 pow(1, 100) = 1 * 1 * ...* 1 = 1
Buat halaman web yang meminta x
dan n
, lalu tampilkan hasil pow(x,n)
.
Jalankan demonya
PS Dalam tugas ini fungsi harus mendukung hanya nilai natural n
: bilangan bulat naik dari 1
.
fungsi kekuatan(x, n) { misalkan hasil = x; untuk (misalkan i = 1; i < n; i++) { hasil *= x; } hasil pengembalian; } misalkan x = prompt("x?", ''); misalkan n = prompt("n?", ''); jika (n < 1) { alert(`Power ${n} tidak didukung, gunakan bilangan bulat positif`); } kalau tidak { waspada( kekuatan(x, n) ); }