news

Rabu, 10 Juni 2020

Belajar Function Dasar Javascript Hingga Arrow Function


Potongan kode pada materi ini:


Fungsi merupakan bagian penting dari bahasa pemrograman. Sebelum ES6, JavaScript tidak melakukan improvisasi yang signifikan pada penulisannya. Hal ini membuat JavaScript terlihat monoton padahal fungsi sendiri banyak sekali dituliskan ketika kita mengembangkan website/aplikasi.
Pada ES6 banyak improvisasi pada penulisan fungsi. Sekarang kita bisa menuliskan fungsi secara singkat dengan memanfaatkan arrow function, membuat fungsi sebagai class dengan hadirnya keyword class, menetapkan nilai default pada parameter fungsi, dan sebagainya.
Penasaran seperti apa perubahannya? Ayo kita bahas mulai dari arrow function

Arrow Function Expression

ES6 memperkenalkan fungsi baru yang dinamakan arrow function expression atau lebih dikenal sebagai arrow function. Arrow function mirip seperti regular function secara perilaku, namun penulisannya jauh berbeda. Sama seperti namanya, fungsi didefinisikan dengan menggunakan tanda panah (=>) dan tentu penulisan fungsi dengan arrow ini akan lebih singkat.
Untuk gambaran awal, perhatikan penulisan regular fungsi sebagai callback berikut:

  1. const upperizedNames = ["Dimas", "Widy", "Buchori"]

  2.     .map(function(name) {

  3.         return name.toUpperCase();

  4. });

  5.  

  6. console.log(...upperizedNames);

  7.  

  8. /* output:

  9. DIMAS WIDY BUCHORI

  10. */


Sedangkan menggunakan arrow function akan tampak seperti ini:

  1. const upperizedNames = ["Dimas", "Widy", "Buchori"]

  2.     .map(name => name.toUpperCase());

  3.  

  4. console.log(...upperizedNames);

  5.  

  6. /* output:

  7. DIMAS WIDY BUCHORI

  8. */


Pada kasus fungsi yang dituliskan dalam satu baris dengan arrow function kita dapat menghapus kata function, tanda kurung, tanda kurawal, kata return, dan semicolon (;). Kita hanya perlu menambahkan tanda panah (=>) di antara parameter dan kode fungsinya.
202003121515581fc4405ca9a25eada9cbaf9598bf18e1.gif
Lihat betapa sederhananya jika kita menggunakan arrow function

Regular function vs Arrow Function

Sekilas kita sudah tahu seperti apa arrow function, namun mungkin bila kita sama sekali belum pernah mencobanya kita akan dibuat bingung. Pasalnya, penulisannya dibandingkan reguler function jauh berbeda. 
Selain perbedaan dari segi sintaksis, terdapat juga perbedaan perilaku antara keduanya. 
Regular function dapat berupa function declaration atau function expression, namun arrow function hanya berupa function expression saja. Itu sebabnya arrow function memiliki nama lengkap “arrow function expressions”.

  1. // function declaration

  2. function sayHello(greet) {

  3.     console.log(`${greet}!`);

  4. }

  5.  

  6.  

  7. // function expression

  8. const sayName = function (name) {

  9.     console.log(`Nama saya ${name}`)

  10. }



  1. // function expression

  2. const sayHello = greet => console.log(`${greet}!`);

  3. const sayName = name => console.log(`Nama saya ${name}`);



Karena arrow function merupakan sebuah expression, maka ia hanya dapat digunakan untuk disimpan pada variabel (seperti contoh kode di atas), sebagai argumen pada sebuah fungsi, dan sebagai nilai dari properti objek.

  1. const sayName = name => console.log(`Nama saya ${name}`);



  1. ["Dimas", "Widdy", "Buchori"].forEach(name => console.log(`Nama saya ${name}`));




  1. const user = {

  2.     introduce: name => console.log(`Nama saya ${name}`)

  3. }



Function Parameter

Pada penggunaan arrow function kita melihat bahwa variabel yang diletakan sebelum tanda panah (=>) adalah merupakan parameter dari fungsi. 

  1. // name merupakan parameter dari fungsi

  2. const sayName = name => console.log(`Nama saya ${name}`);


Namun penulisan tersebut hanya berlaku jika fungsi memiliki satu parameter saja. Lantas bagaimana jika kita ingin membuat fungsi yang memiliki lebih dari satu parameter atau tanpa sebuah parameter? Hal itu sangat biasa dilakukan bukan? 
Pada arrow function jika terdapat dua atau lebih parameter fungsi kita perlu membungkusnya dengan tanda kurung seperti ini: 

  1. const sayHello = (name, greet) => console.log(`${greet}, ${name}!`);

  2.  

  3. sayHello("Dimas", "Selamat Pagi")

  4.  

  5. /* output:

  6. Selamat Pagi, Dimas!

  7. */


Namun jika kita sama sekali tidak membutuhkan parameter, biarkan saja tanda kurung tersebut kosong.

  1. const sayHello = () => console.log("Selamat pagi semuanya!");

  2.  

  3. sayHello()

  4.  

  5. /* output:

  6. Selamat pagi semuanya!

  7. */


Atau beberapa developer biasanya mengubah tanda kurung menjadi garis bawah (_) agar penulisannya lebih simpel.

Block Body Function

Fungsi merupakan mini program sehingga sangat mungkin terdapat lebih dari satu logika di dalamnya. Seperti yang kita ketahui bahwa logika-logika pada pemrograman terdiri dari banyak expression ataupun statement
Pada contoh kode arrow function sebelumnya kita hanya menuliskan satu buah expression sehingga penulisannya bisa sangat ringkas. Namun bagaimana jika dalam sebuah fungsi terdapat banyak logika di dalamnya? Apakah bisa dituliskan menggunakan arrow function? Jawabannya tentu bisa!
Sama seperti regular function, arrow function sebenarnya tidak benar-benar menghilangkan tanda kurung kurawal ({ }) dalam penulisannya. Tanda kurung kurawal pun berfungsi sama seperti regular function yakni menampung body function di mana tempat logika fungsi dituliskan. Penulisan tanda kurung kurawal menjadi opsional ketika body fungsi hanya terdiri dari satu expression atau statement saja.
Jika kita butuh lebih dari satu baris dalam body function, kita bisa menuliskannya seperti ini:

  1. const sayHello = language => {

  2.     if(language.toUpperCase() === "INDONESIA") {

  3.         return "Selamat Pagi!";

  4.     } else {

  5.         return "Good Morning!";

  6.     }

  7. }

  8.  

  9. console.log(sayHello("Indonesia"));

  10.  

  11. /* output:

  12. Selamat Pagi!

  13. */



Selain itu juga, kita perlu menuliskan kembali keyword return agar fungsi tersebut dapat mengembalikan nilai

This Keyword

Perbedaan karakteristik dari arrow function dan regular function selanjutnya ada pada penggunaan keyword this. Penjelasan dari this sendiri menyusul di materi class. Namun kita akan bahas sedikit mengenai ini untuk menggambarkan perbedaan ketika this digunakan oleh arrow function dan regular function.
Jika sebuah regular function dipanggil dengan menggunakan keyword new. Maka nilainya akan menjadi objek, contohnya:

  1. function People(name, age, hobby) {

  2.     this.name = name;

  3.     this.age = age;

  4.     this.hobby = hobby;

  5. }

  6.  

  7. const programmer = new People("John", 18, ["Coding", "Read book", "Ping-pong"]);

  8.  

  9. console.log(programmer.name);

  10. console.log(programmer.age);

  11. console.log(programmer.hobby);

  12.  

  13. /* output:

  14. John

  15. 18

  16. [ 'Coding', 'Read book', 'Ping-pong' ]

  17. */


Objek yang dibuat menggunakan function dengan keyword new, sama halnya seperti kita membuat objek seperti menggunakan objek literals { }.

  1. const programmer = {

  2.     name: "John",

  3.     age: 18,

  4.     hobby: ["Coding", "Read book", "Ping-Pong"]

  5. }

  6.  

  7. console.log(programmer.name);

  8. console.log(programmer.age);

  9. console.log(programmer.hobby);

  10.  

  11. /* output:

  12. John

  13. 18

  14. [ 'Coding', 'Read book', 'Ping-pong' ]

  15. */


Pada objek, this keyword mengembalikan nilai objeknya sendiri. this dapat digunakan untuk mengelola properti pada objeknya. Namun jika fungsi dipanggil tanpa menggunakan keyword new, this akan memiliki nilai global object (Window jika di browser).
Sedangkan fungsi yang dibuat dengan menggunakan gaya arrow tidak akan pernah memiliki nilai this, yang artinya kita tidak pernah bisa membuat objek menggunakan arrow function. Jika kita menggunakan this pada arrow function maka nilai this tersebut merupakan nilai objek di mana arrow function itu berada.
Perhatikan kedua contoh kode berikut:

  1. function People(name, age, hobby) {

  2.     this.name = name;

  3.     this.age = age;

  4.     this.hobby = hobby;

  5. }

  6.  

  7.  

  8. // menambahkan introMyself ke People

  9. People.prototype.introMyself = function () {

  10.     // this -> People

  11.     setTimeout(function() {

  12.        // this -> ??

  13.         console.log(`Hello! Nama saya ${this.name}, umur saya ${this.age}.`)

  14.         console.log(`Hobby saya adalah ${this.hobby}`)

  15.     }, 300)

  16. }

  17.  

  18.  

  19. const programmer = new People("John", 18, ["Coding", "Read book", "Ping-pong"]);

  20. programmer.introMyself();

  21.  

  22.  

  23. /* output:

  24. Hello! Nama saya undefined, umur saya undefined.

  25. Hobby saya adalah undefined

  26. */




  1. function People(name, age, hobby) {

  2.     this.name = name;

  3.     this.age = age;

  4.     this.hobby = hobby;

  5. }

  6.  

  7.  

  8. // menambahkan introMyself ke People

  9. People.prototype.introMyself = function () {

  10.     // this -> People

  11.     setTimeout(() => {

  12.         // this -> People

  13.         console.log(`Hello! Nama saya ${this.name}, umur saya ${this.age}.`)

  14.         console.log(`Hobby saya adalah ${this.hobby}`)

  15.     }, 300)

  16. }

  17.  

  18.  

  19. const programmer = new People("John", 18, ["Coding", "Read book", "Ping-pong"]);

  20. programmer.introMyself();

  21.  

  22.  

  23.  

  24.  

  25. /* output:

  26. Hello! Nama saya John, umur saya 18.

  27. Hobby saya adalah Coding,Read book,Ping-pong

  28. */





Fungsi yang dituliskan di dalam setTimeout() dipanggil tanpa new. Itu berarti nilai dari this jika digunakan di dalam fungsi tersebut adalah global object. Itulah mengapa output akan menghasilkan nilai undefined ketika properti nameage, dan hobby dipanggil.
Berbeda ketika kita menuliskan arrow function di dalam setTimeout(), nilai this memiliki nilai objek sesuai dengan konteksnya (People). Arrow function akan sangat berguna untuk kasus seperti ini.

Default Parameters

Fitur lainnya pada ES6 yang sangat bermanfaat adalah kita dapat menetapkan nilai default pada parameter fungsi. Dengan menggunakan default parameters, nilai pada parameter tidak akan menghasilkan undefined walaupun kita tidak memberikan nilai ketika fungsi tersebut dipanggil. Default parameter dapat digunakan pada regular function ataupun arrow function.
Berikut contoh dari penggunaan default parameter:

  1. function sayHello(name = "Stranger", greet = "Hello") {

  2.     console.log(`${greet} ${name}!`);

  3. }

  4.  

  5. sayHello("Dimas", "Hai");

  6. sayHello();

  7.  

  8. /* output:

  9. Hai Dimas!

  10. Hello Stranger!

  11. */



  1. const sayHello = (name = "Stranger", greet = "Hello") => console.log(`${greet} ${name}!`);

  2.  

  3.  

  4. sayHello("Dimas", "Hai");

  5. sayHello();

  6.  

  7.  

  8. /* output:

  9. Hai Dimas!

  10. Hello Stranger!

  11. */


Pada contoh di atas, kita menggunakan tanda assignment (=) untuk menetapkan parameter name dengan nilai default “Stranger”, dan parameter greet dengan nilai default “Hello”
Hal ini sangat berguna ketika kita memanggil fungsi sayHello() tanpa menetapkan nilai parameter di dalamnya, karena walaupun kita tidak menetapkan nilainya, kedua parameter tersebut tidak akan menghasilkan undefined

Solution : Arrow Function

Apakah Anda sudah berhasil mengubah seluruh penulisan function yang ada dengan menggunakan arrow function? Jika belum, mari kita lakukan hal tersebut bersama-sama.
Dalam club project, kita hanya menggunakan function declaration pada pembuatan function constructor DataSource. Sedangkan fungsi - fungsi yang lainnya merupakan function expression dan function callback. Yang artinya fungsi-fungsi tersebut dapat secara leluasa kita ubah menggunakan arrow function.
Mulai dari penulisan fungsi yang berada pada berkas main.js. Kita dapat mengubah penulisan fungsinya menggunakan arrow function. Alhasil, kode pada main.js akan tampak seperti ini:
  1. const main = () => {
  2.    const searchElement = document.querySelector("#searchElement");
  3.    const buttonSearchElement = document.querySelector("#searchButtonElement");
  4.    const clubListElement = document.querySelector("#clubList");
  5.  
  6.    const onButtonSearchClicked = () => {
  7.        const dataSource = new DataSource(renderResult, fallbackResult);
  8.        dataSource.searchClub(searchElement.value);
  9.    };
  10.  
  11.    const renderResult =  results => {
  12.        clubListElement.innerHTML = "";
  13.        results.forEach(club => {
  14.            const {name, fanArt, description} = club;
  15.            const clubElement = document.createElement("div");
  16.            clubElement.setAttribute("class", "club");
  17.  
  18.            clubElement.innerHTML = `
  19.                <img class="fan-art-club" src="${fanArt}" alt="Fan Art">
  20.                <div class="club-info">
  21.                    <h2>${name}</h2>
  22.                    <p>${description}</p>
  23.                </div>`;
  24.  
  25.            clubListElement.appendChild(clubElement);
  26.        })
  27.    };
  28.  
  29.    const fallbackResult = message => {
  30.        clubListElement.innerHTML = "";
  31.        clubListElement.innerHTML += `<h2 class="placeholder">${message}</h2>`;
  32.    };
  33.  
  34.    buttonSearchElement.addEventListener("click", onButtonSearchClicked);
  35. };

Lalu kita juga dapat mengubah gaya penulisan fungsi handler untuk filter di dalam searchClub pada berkas data-source.js:

  1. const filteredClubs = clubs.filter(club => club.name.toUpperCase().includes(keyword.toUpperCase()));


Untuk memastikan perubahan yang kita lakukan sudah benar silakan Anda coba buka berkas index.html pada browser. Jika aplikasi berjalan dengan lancar, maka fitur arrow function berhasil diterapkan dengan baik.
Namun jika aplikasi tidak berjalan lancar dan menghasilkan eror pada console browser, jangan malu untuk bertanya pada forum diskusi ya!
Langkah dari solution ini bisa Anda temukan juga pada repository berikut: https://github.com/dicodingacademy/a163-bfwd-labs/tree/105-club-finder-arrow-function-solution