10 Functions
Fungsi merupakan suatu bentuk abstraksi untuk mewakili proses yang menghubungkan input dan output. Beberapa bahas pemrograman lain yang cukup lama seperti C, C++, dan Fortran, menyebuh fungsi sebagai subroutine atau procedure.
Maksud dari proses abstraksi tersebut adalah, dengan menggunakan fungsi kita bisa mewakili suatu prosedur yang panjang dan dipakai berulang dan menamakan prosedur tersebut sebagai suatu fungsi. Hal ini tentunya akan mempermudah pekerjaan kita, ketika kita dihadapkan dengan masalah yang hampir serupa, dan kita cukup menggunakan (memanggil) fungsi tersebut tanpa harus mengetik berulang-ulang proses yang diwakili fungsi tersebut.
Kemampuan berabstraski sangat diperlukan untuk bisa menyusun fungsi yang benar dan efisien. Pembuatan fungsi dimulai dengan menuliskan prosedur secara modular (terpisah-pisah), setelah terlihat strukturnya kita bisa menggabungkan prosedur tersebut ke dalam suatu fungsi.
Dengan fungsi, kita juga dapat mengimplementasi berbagai macam algoritma-algoritma pemecahan masalah. Di akhir pertemuan tentang fungsi ini, kita akan mencoba untuk menyusun algoritma sederhana
Beberapa hal yang akan kita pelajari di sesi ini adalah: 1. Istilah-istilah dasar dalam fungsi 2. Cara mendeklarasikan fungsi 3. Pemanggilan fungsi 4. a brief intro to functional programming
10.1 Some basics terminology in JavaScript's function
Invoked: merupakan peristiwa saat kita memanggil fungsi yang telah didefinisikan
parameterized: keadaan suatu variable input atau variabel yang dimuat oleh suatu fungsi bersifat lokal (telah terparameterisasi)
parameter: variable input yang dimiliki oleh fungsi yang berfungsi sebagai penanda (identifier)
argument: merupakan nilai yang akan diinputkan ke dalam fungsi atau nilai yang diberikan ke variabel input. Proses pemberian argument terjadi saat fungsi dipanggil (function invocation)
method: fungsi yang secara khusus didefinisikan sebagai property suatu object
constructor: fungsi yang secara khusus didefinisikan untuk melakukan pendeklarasian suatu object.
closure: merupakan sifat dari fungsi di JavaScript yang mana suatu definisi fungsi dapat disisipkan dalam suatu fungsi lain dan fungsi yang didefinisikan tersebut dapat mengakses variable di fungsi yang disisipi.
10.2 Function declaration
menggunakan kata kunci
function
func-def-with-function.js
// Mencetak `property name` dan `property value` dari suatu object o function printops(o) { for (let p in o) { console.log(`${p}: ${o[p]}`); } } // Melakukan penghitungan jarak antara dua titik (x1, y1) dan (x2, y2) function distance(x1, y1, x2, y2) { let dx = x2 - x1; let dy = y2 - y1; return Math.sqrt(dx*dx + dy*dy); } // FUngsi rekursif yang memanggil dirisnya sendiri dan digunakan untuk // menghitung faktorial function factorial(x) { if (x <= 1) return 1; return x * factorial(x-1); } let o = {"apple": 5000, "mango": 7000, "pineapple": 15000}; printops(o); console.log(); let dist = distance(0, 0, 5, 12); // => 13 = sqrt(5^2 + 12^2) console.log("dist: ", dist); console.log(); console.log("factorial(5): ", factorial(5)); // => 120 = 5 x 4 x 3 x 2 x 1
variable yang bernilai suatu function expression
func-def-with-func-expression.js
// Function expression berikut mendefinisikan nilai kuadrat dari argument // yang diberikan kepada fungsi tersebut const square = function(x) { return x*x; }; console.log(square(5)); // Function expression dapat memuat nama yang dapt digunakan // untuk mendefinisikan fungsi rekursif const f = function fact(x) { if (x <= 1) return 1; else return x*fact(x-1); }; console.log(f(5)); // Function expression dapat digunakan sebagai suatu argumen untuk fungsi // yang lain let result = [3, 2, 1].sort(function(a, b) { return a - b; }); console.log(result); // Function expression dapat juga didefinisikan dan langsung di panggil // dengan nilai argument let tensquared = (function(x) { return x*x; }(10)); console.log(tensquared);
Jalan pintas (shortcut) untuk mendefinisikan fungsi: arrow function
func-def-with-arrow-func.js
let result; // Mendefinisikan fungsi jumlahan dua buat variabel x dan y menggunakan arrow // function ( () => {} ) const sum = (x, y) => { return x + y; }; result = sum(25, 75); console.log(result); // Tanpa kurung kurawal dan kata kunci `return` const sumShort = (x, y) => x + y; result = sumShort(25, 75); console.log(result); // Untuk arrow function dengan satu parameter tidak perlu menggunakan kurung const polynomial = x => x*x + 2*x + 3; result = polynomial(1); console.log(result); // Untuk arrow function tanpa argumen dapat menggunakan kurung saja const greeting = () => "Hi!"; result = greeting(); console.log(result); // -- Penggunaan arrow function sebagai argument suatu array method // Digunakan untuk menghapus element yang bernilai null let filtered = [1, null, 2, 3].filter(x => x !== null); console.log(filtered); // Digunakan untuk melakukan kuadrat setiap element array tanpa harus // melakukan perulangan menggunakan array method `map()` let squares = [1, 2, 3, 4].map(x => x*x); console.log(squares);
Fungsi yang memuat fungsi (nested function)
func-def-with-nested-func.js
// Fungsi berikut akan menghitung sisi miring dari suatu segitiga siku-siku // dengan diberikan panjang sisi tegak dan sisi mendatar. // Fungsi yang memuat definisi suatu fungsi (square). Disini fungsi square // dapat memanggil variabel tempat fungsi tersebut didefinisikan, yaitu // dapat mengakses variabel a dan b dari fungsi hypotenuse function hypotenuse(a, b) { function square(x) { return x*x; } return Math.sqrt(square(a) + square(b)); } let result = hypotenuse(5, 12); console.log(result);
10.3 Function invocation
fungsi dipanggil sebagai fungsi
Pada bagian sebelumnya kita secara tidak langsung sudah melakukan pemanggilan fungsi, yaitu menggunakan nama fungsi dan dikuti kurung buka lalu daftar arguments diakhiri dengan kurung tutup.fungsi dipanggil sebagai method
Suatu fungsi yang didefinisikan di dalam suatu object dapat dipanggil sebagai suatu methodsfunc-invoke-with-method.js
// Object calculator yang dapat menyimpan input penjumlahan dan hasil // penjumlahannya let calculator = { operand1: 1, operand2: 1, add() { this.result = this.operand1 + this.operand2 } } // Kita berikan input bilangan yang akan dilakukan penjumlahan calculator.operand1 = 5; calculator.operand2 = 7; // Lakukan proses penjumlahan setelah memasukan inpuit calculator.add(); // Tampilkan hasil penjumlahan console.log(calculator.result);
pemanggilan fungsi secara tidak langsung menggunakan
call()
danapply()
func-invoke-with-call-and-apply.js
let arrayOfNumbers = [4, 2, 3, 1, 1, 2, 3, 5, 1, 3, 3]; let biggest; // Pemanggilan fungsi Math.max secara langsung biggest = Math.max(...arrayOfNumbers) console.log(biggest); // Kita menggunakan Math object (object bawaan dari JavaScript) // yng memuat semua type bilangan. Kita terapkan fungsi Math.max // ke arrayOfNumber tetapi secara tidak langsung menggunakkan .appyly // Math.max akan menjadi method dari Math object dan juga arrayNumbers // akan menjadi argument dari Math.max dan kita tidak perlu melakukan // unpack menggunakan spread operator biggest = Math.max.apply(Math, arrayOfNumbers) console.log(biggest); // with .call you have to use spread operator to unpack the elements biggest = Math.max.call(Math, ...arrayOfNumbers); console.log(biggest);
10.4 Function arguments and parameters
Di bagian ini kita akan mempelajari bagaimana suatu arguments digunakan dalam suatu fungsi.
Optional parameters dan default parameters
Di bagian ini kita akan melihat bagaimana optional parameter dan default parameters. diimplementasikan ke dalam suatu fungsi. Optional parameters disini berarti kita bisa inputkan argument atau tidak ke optional parameters tersebutoptional-params.js
// Fungsi berikut akan mengambil property name dari parameter obj // dan menambahkan setiap property name ke dalam parameter arr. function getPropertyNames(obj, arr) { // Apabila parameter arr tidak digunakan, maka didefinisikan dengan // nilai arr = [] (empty array) if (arr === undefined) { arr = []; } // Menambahkan setiap property name dari parameter obj ke parameter arr for (let property in obj) { arr.push(property); } return arr; } // Object berikut menggambarkan konfigurasi laman website yang diambil // dari berkas .css let obj = { 'max-width': '36rem', 'padding': ['0', '1rem'], 'margin': ['3rem', 'auto', '6rem'] }; let arr = ['display']; // konfigurasi lain yang hanya memuat property name // Pemanggilan fungsi pengumpulan property names dari parameters obj // namun tanpa parameters arr (parameter arr disini opsional) let objPropNames = getPropertyNames(obj); console.log(objPropNames); // => ['max-width', 'padding', 'margin'] // Pemanggilan fungsi pengumpulan property names dari parameter obj // dengan optional parameter arr yang telah terisi element 'display' let objPropNamesWithOption = getPropertyNames(obj, arr); console.log(objPropNamesWithOption);
Menurut contoh di atas, kita bisa input-kan
arr
sebagai optional parameter. Jika kita tidak berikan inputarr
ke optional parameter (parameter urutan kedua), maka secara otomatis fungsi akan mendeklarasikan parameterarr
sebagai empty array.Berikutnya adalah contoh fungsi dengan default parameter
default-params.js
function getPropertyNames02(obj, arr=[]) { for (let property in obj) { arr.push(property); } return arr; } // Object berikut menggambarkan konfigurasi laman website yang diambil // dari berkas .css let obj = { 'max-width': '36rem', 'padding': ['0', '1rem'], 'margin': ['3rem', 'auto', '6rem'] }; let arr = ['display']; // konfigurasi lain yang hanya memuat property name // Pemanggilan fungsi pengumpulan property names dari parameters obj // namun tanpa parameters arr (parameter arr disini akan diset secara // otomatis sebagai array kosong) let objPropNames = getPropertyNames(obj); console.log(objPropNames); // => ['max-width', 'padding', 'margin'] // Pemanggilan fungsi pengumpulan property names dari parameter obj // dengan default parameter arr yang telah terisi element 'display' let objPropNamesWithOption = getPropertyNames(obj, arr); console.log(objPropNamesWithOption);
Terlihat dengan menggunakan default parameter, deklarasi fungsi lebih ringkas dan mudah dimengerti bahwa ketika parameters
arr
tidak diberikan sebagai argument dalam pemanggilan fungsi, maka secara default akan diberikan nilai awalan empty array.Rest paramaters
Ketika jumlah argument yang harus kita berikan dalam suatu fungsi saat fungsi tersebut dipanggil ((invocation)) sangat banyak, maka rest parameters dapat membantu kita tanpa perlu meng-inputkan satu-satu. Bayangkan jika jumlah argument suatu fungsi yang dipanggil sejumlah satu juta arguments.Berikut contoh penggunaan rest parameters untuk fungsi pencarian nilai maksimum;
rest-params-max-func.js
// Fungsi untuk menghitung nilai maksimumn. Terlihat disini digunakan // rest parameters yang diawali oleh tiga titik. // Output dari fungsi ini adalah nilai maksimum dari inputan yang diberikan function max(...rest) { let maxValue = -Infinity; for (let n of rest) { if (n > maxValue) { maxValue = n; } } // Return the biggest return maxValue } // Disini kita memberikan input arguments lebih dari satu, namun // di dalam pendeklarasian fungsi kita hanya cukup menggunakan rest // parameter menggunakan ...rest let result = max(1, 10, 100, 2, 3, 1000, 4, 5, 6); console.log(result);
Spread operator untuk argument fungsi yang dipanggil/invoked
Ketika input argument yang disisipkan lebih dari satu ataupun banyak, misalnya 20 arguments, cara yang paling efisien adalah menggunakan spread operator di arguments (ingat kembali perbedaan arguments dan parameters). Berikut ini adalah pemanggilan fungsi menggunakan spread operator untuk input arguments lebih dari satu. Contoh fungsi yang digunakan tetap sama yaitu menghitung nilai maksimumspread-op-max-func.js
function max(...rest) { let maxValue = -Infinity; for (let n of rest) { if (n > maxValue) { maxValue = n; } } // Return the biggest return maxValue } let inputArr = [1, 10, 100, 2, 3, 1000, 4, 5, 6]; let result = max(...inputArr) // Disini kita menggunakan spread operator // pada argument inputArr console.log(result);
10.5 Function as values
Karena fleksibiltas fungsi, kita dapat menggunakan fungsi sebagai suatu nilai.
Pengunaan fungsi sebagai nilai suatu variable
Pada pertemuan sebelumnya di bagian pendeklarasian fungsi, kita telah mengetahui bahwa fungsi dapat di-assign ke suatu variable. Jika yang kita assign adalah nama fungsinya saja, tanpa arguments maka yang terjadi adalah kita membuat referensi baru ke fungsi itu dengan nama variable tersebut.func-as-vals-variable-assign.js
// Berikut adalah fungsi untuk melakukan pengkuadratan function square(x) { return x*x; } // Kita assign fungsi tersebut (tanpa argument) ke variable s let s = square; // Kita dapat memanggil fungsi tersebut (invocation) dengan nama fungsi square // atau dengan variable s console.log(square(16)); console.log(s(16));
Penggunaan fungsi sebagai nilai dari suatu property
Sedikit berbeda pada pertemuan sebelumnya yang menggunakan fungsi sebagai method suatu object. Di bagian ini kita dapat memberikan nilai suatu property* dengan suatu fungsi. Property dari object tersebut akan beralih fungsi sebagai nama fungsi atau bisa juga dilihat sebagai method dari object tersebut.func-as-vals-props-vals.js
Penggunaan fungsi sebagai nilai untuk element suatu array
Di bagian ini hanyalah sedikit kemungkinan penerapan tidak umum dari fungsi yang digunakan sebagai element suatu array. Disini hanya ditambahkan sebagai kemungkinan bahwa kita dapat mengkonstruksi berbagai macam hal dengan fungsi sekalipun terlihat anehfunc-as-vals-arr-element.js
Penggunaan fungsi sebagai nilai untuk argument fungsi lain
Penggunaan ini adalah yang paling sering digunakan dalam penyusunan program menggunakan JavaScript. Disini fungsi dijadikan sebagai argument untuk nilai parameter suatu fungsi yang lain. Sebagai contoh kita akan membuat suatu program kalkulator yang mana fungsi-fungsi aritmatik seperti kali, bagi, tambah, kurang akan menjadi input argument ke dalam fungsi kalkulatorfunc-as-vals-input-args.js
// Kita definisikan fungsi aritmatika dari fungsi kalkulator function add(x, y) { return x + y; } function subtract(x, y) { return x - y; } function multiply(x, y) { return x * y; } function divide(x, y) { return x / y; } // Berikut adalah fungsi yang mendefinisikan kalkulator function calculate(operator, operand1, operand2) { return operator(operand1, operand2); } // Menghitung nilai ekspresi (1 + 2) * (3 - 2) / 3; let result = calculate( divide, calculate( multiply, calculate( add, 1, 2), calculate( subtract, 3, 2)), 3); console.log(result);
Pada program di atas kita melihat bahwa argument kedua dan ketiga saat proses pembagian (
divide
), merupakan pemanggilan fungsicalculate
. Sampai pada akhirnya pada level operasi terdalam (yang memiliki kurung, yaitu penjumlahan dan pengurangan). Fungsi aritmatika:add
,subtract
,multiply
, dandivide
digunakan sebagai input argument fungsicalculate
. Demikian juga fungsicalculate
digunakan sebagai input arguments fungsicalculate
10.6 Functional programming
Dibagian ini kita hanya menyentuh permukaan dari paradigma functional programming. Disini kita hanya menerapkan aplikasi functional programming untuk memproses arrays
Berikut adalah implementasi perhitungan standard deviasi menggunakan looping. Secara singkat, standard deviasi mengukur seberapa jauh distribusi data terhadap nilai rata-rata.
compute-stddev-conventional.js
const formatStr = require('@stdlib/string-format')
let data = [1, 1, 3, 3, 5, 7, 7, 9, 9];
// Menghitung rata-rata dengan cara menjumlahkan semua element
// dan membaginya dengan banyaknya element
let total = 0;
for (let i = 0; i < data.length; i++) {
total += data[i];
}
let mean = total / data.length;
// Menghitung standard deviasi, pertama menghitung jumlahan
// kuadrat deviasi setiap element terhadap rata-rata.
// Setelah itu di bagi dengan (jumlah data - 1)
total = 0;
for (let i = 0; i < data.length; i++) {
let deviation = data[i] - mean;
total += deviation * deviation;
}
let stddev = Math.sqrt(total/(data.length - 1));
console.log(formatStr('%.2f', stddev)); // => 3.16
Berikut ini adalah implementasi program di atas menggunakan paradigma
fungsional. Disini kita lihat tidak ada control structure loop lagi, dan
semuanya diganti menjadi fungsi map
dan reduce
. Kita akan menjelaskan
lebih detail di sesi kelas terkait map
dan reduce
.
compute-stddev-func-prog.js
const formatStr = require("@stdlib/string-format");
const map = function(a, ...args) { return a.map(...args); };
const reduce = function(a, ...args) { return a.reduce(...args); };
const sum = (x, y) => x + y;
const square = x => x * x;
let data = [1, 1, 3, 3, 5, 7, 7, 9, 9];
let mean = reduce(data, sum)/data.length;
let deviations = map(data, x => x - mean);
let stddev = Math.sqrt(
reduce(map(deviations, square), sum)/(data.length - 1));
console.log(formatStr("%.2f", stddev)); // => 3.16
Exercises
Sebutkan 3 kegiatan yang kalian lakukan sehari-hari yang dapat diubah menjadi suatu fungsi. Implementasi fungsi tersebut kedalam JavaScript. Berikan juga contoh penggunaannya.
Berikut contoh salah satu kegiatan yang mungkin.
Buatlah suatu fungsi untuk mengkonversi suatu bilangan ke bentuk string yang merupakan pembacaan bilangan tersebut:
- 1, menjadi ‘satu’,
- 2, menjadi ‘dua’,
- 3, menjadi ‘tiga’,
- 4, menjadi ‘empat’,
- 5, menjadi ‘lima’,
- dst.
Fungsi yang akan kalian buat tersebut harus mampu mengkonversi hingga bilangan ke-100.
Buatlah sebuah fungsi untuk menghitung besar pengeluaran Yasuke (lihat slide di pertemuan tentang Object) diberikan input weekly expense Yasuke selama seminggu.
Berikut data weekly expense Yasuke selama seminggu.
Monday, March 21: * Breakfast at a local food stall - 20,000 * Transportation to work - 10,000 * Lunch with colleagues - 50,000 * Snacks from a convenience store - 15,000 * Dinner at home - 30,000 Tuesday, March 22: * Breakfast at home - 10,000 * Coffee from a cafe - 25,000 * Groceries for the week - 150,000 * Lunch from a food delivery app - 35,000 * Snack from a street vendor - 10,000 Wednesday, March 23: * Breakfast at home - 10,000 * Transportation to work - 10,000 * Lunch from a food court - 40,000 * Afternoon tea from a bakery - 20,000 * Dinner at home - 40,000 Thursday, March 24: * Breakfast at home - 10,000 * Coffee from a cafe - 25,000 * Transportation to work - 10,000 * Lunch from a food delivery app - 35,000 * Snacks from a convenience store - 10,000 * Dinner at home - 40,000 Friday, March 25: * Breakfast at home - 10,000 * Transportation to work - 10,000 * Lunch from a food court - 40,000 * Afternoon snack from a street vendor - 15,000 * Dinner at a friend's house - 0 (free) Saturday, March 26: * Brunch with friends at a cafe - 80,000 * Transportation to a shopping mall - 20,000 * Shopping for clothes and accessories - 300,000 * Dinner at home - 50,000 Sunday, March 27: * Breakfast at home - 10,000 * Transportation to a park - 15,000 * Entrance fee to the park - 5,000 * Lunch from a food stall at the park - 30,000 * Snacks and drinks from a vending machine - 10,000 * Dinner at home - 40,000
Fungsi yang dibuat juga harus mampu menghitung rata-rata pengeluaran harian dari Yasuke.