Potongan kode untuk materi ini: https://repl.it/@dicodingacademy/163-02-variable-declaration?lite=true
Awalnya memahami deklarasi variabel di JavaScript agak sedikit rumit. Karena pada JavaScript berbeda dari bahasa pemrograman berbasis bahasa C yang umumnya variabel tersedia pada blok ketika ia dibuat. Namun pada JavaScript kasus tersebut tidak selalu benar.
Variabel pada JavaScript akan dibuat tergantung bagaimana cara kita mendeklarasikannya. Sedikit membingungkan bukan? Jangan khawatir, kita akan bahas masalah ini lebih detail.
Deklarasi var dan Hoisting
Variabel yang dideklarasikan menggunakan var akan selalu diangkat pada tingkatan atas sebuah fungsi walaupun kita menuliskannya bukan pada tingkatan atas fungsi. Proses pengangkatan deklarasi variabel ini disebut dengan hoisting.
Perhatikan contoh kode berikut:
- function makeTea(isCold) {
- if(isCold) {
- var tea = "Make an Ice Tea!"
- } else {
- var tea = "Make a Hot Tea!"
- }
- return tea;
- }
- console.log(makeTea(false));
- /* output
- Make a Hot Tea!
- */
Kode di atas akan menghasilkan output “Make a Hot Tea!”. Mengapa bisa demikian? Padahal kita mendeklarasikan variabel tea di dalam blok if dan blok else. Seharusnya kita tidak dapat mengaksesnya diluar blok tersebut dan menghasilkan error:
- ReferenceError: tea is not defined
Nah, inilah yang akan kita dapatkan jika menggunakan keyword var dalam mendeklarasikan variabel. Di belakang layar, JavaScript mengangkat proses deklarasi variabel tea pada tingkatan atas fungsi. Sehingga variabel tersebut akan tersedia selama kita berada di dalam fungsi makeTea. Dengan begitu kode sebenarnya akan menjadi seperti ini:
- function makeTea(isCold) {
- var tea;
- if(isCold) {
- tea = "Make an Ice Tea!"
- } else {
- tea = "Make a Hot Tea!"
- }
- return tea;
- }
- console.log(makeTea(false));
- /* output
- Make a Hot Tea!
- */
Bahkan karena proses hoisting inilah kita bisa menginisialisasi nilai dan menggunakan variabel sebelum ia dideklarasikan. Hal ini sedikit tidak masuk akal bukan?
- function getFood() {
- food = "choocolate";
- console.log(food);
- var food;
- }
- getFood();
- /* output
- choocolate
- */
Proses hoisting menjadi kontroversial karena tidak jarang developer yang dibuat bingung akan hal ini.
let dan const
Sejak ES6 selain var, menginisialisasikan variabel dapat menggunakan let dan const. ES6 melakukan improvisasi pada deklarasi variabel karena menggunakan var terdapat beberapa hal yang kontroversial, salah satunya hoisting yang sudah kita bahas tadi.
Variabel yang dideklarasikan dengan let atau const akan menghilangkan permasalahan dari hoisting karena variabel akan tersedia pada cakupan block (sama seperti bahasa pemrograman berbasis C), bukan pada fungsi.
Perhatikan kode berikut. Mari gunakan contoh kode sebelumnya namun menggunakan let dalam mendeklarasikan variabel:
- function makeTea(isCold) {
- if(isCold) {
- let tea = "Make an Ice Tea!"
- } else {
- let tea = "Make a Hot Tea!"
- }
- return tea;
- }
- console.log(makeTea(false));
- /* output
- ReferenceError: tea is not defined
- */
Variabel yang dideklarasikan menggunakan let ataupun const juga tidak dapat diakses sebelum ia dideklarasikan, karena variabel akan terhenti pada tempat yang biasa disebut dengan temporal dead zone hingga akhirnya variabel tersebut dideklarasi. Jika kita mencoba melakukannya maka akan menghasilkan eror yang sama.
- function getFood() {
- food = "choocolate";
- console.log(food);
- let food;
- }
- getFood();
- /* error:
- ReferenceError: food is not defined
- */
let dan const menjadi solusi dari permasalahan hoisting pada JavaScript. Hal ini menjadikan JavaScript lebih ketat dalam pendeklarasian variabel, sehingga dapat meminimalisir peluang terjadinya bug.
Aturan penggunaan let dan const
Setelah kita mengetahui mengapa kita harus menggunakan let dan const daripada var dalam mendeklarasikan variabel, lantas apa perbedaan dari let dan const itu sendiri? Kapan kita harus menggunakan let daripada const? Begitu pula sebaliknya.
Variabel yang dideklarasikan dengan let atau pun const memiliki kesamaan dan perbedaan karakteristik. Persamaannya adalah variabel yang dideklarasikan dengan let atau const tidak dapat di deklarasikan ulang pada cakupan yang sama (kita dapat melakukan hal ini ketika menggunakan var).
- let name = "John";
- let name = "Doe";
- console.log(name);
- /* error:
- SyntaxError: Identifier 'name' has already been declared
- */
Perbedaanya antara let dan const adalah jika kita menggunakan let maka variabel tersebut dapat diinisialisasi ulang nilainya. Sedangkan const tidak bisa, sehingga jika kita menggunakan const pastikan kita langsung menginisialisasi nilai dari variabel tersebut.
- let name = "John";
- name = "Doe";
- console.log(name);
- /* output:
- Doe
- */
Jadi intinya kapan kita harus menggunakan let dan const? Untuk aturan umum penggunaanya adalah sebagai berikut:
- Gunakan let ketika variabel yang kita buat akan diinisialisasikan kembali nilainya.
- Gunakan const ketika variabel yang kita buat tidak ingin diinisialisasikan kembali nilainya.
const merupakan cara yang paling ketat dalam membuat variabel, sehingga pastikan kita menggunakan const jika memang kita tidak berencana untuk menginisialisasikan kembali nilainya.
Ada sedikit catatan, bahwa mengubah dan menginisialisasikan ulang nilai pada variabel merupakan hal yang berbeda. Kita bisa lihat perbedaanya dengan jelas ketika sebuah variabel tersebut merupakan array atau objek.
Menginisialisasikan ulang
- const fruits = ["apple", "orange"];
- fruits = ["apple", "orange", "banana"];
- console.log(fruits);
- /* output
- TypeError: Assignment to constant variable. */
- const people = { name: "John", age: 18 };
- people = { name: "John", age: 18, regency: "Bandung" };
- console.log(people);
- /* TypeError: Assignment to constant variable. */
Mengubah
- const fruits = ["apple", "orange"];
- fruits.push("banana");
- console.log(fruits);
- /* output
- [ 'apple', 'orange', 'banana' ]
- */
- const people = { name: "John", age: 18 }
- people.regency = "Bandung"
- console.log(people);
- /* output
- { name: 'John', age: 18, regency: 'Bandung' }
- */
Membuat variabel dengan const akan membuat variabel tersebut bersifat read-only, tapi bukan berarti tidak dapat diubah nilainya. Mungkin variabel yang menampung nilai primitif seperti string, number, boolean akan sulit mengubah nilainya tanpa melalui inisialisasi ulang
Solution : Variable Declaration
Apakah Anda sudah menerapkan seluruh deklarasi menggunakan standar ES6? Jika belum, mari kita lakukan hal tersebut bersama-sama.
Jika kita lihat pada seluruh kode yang ada, seluruh deklarasi variabel masih menggunakan var. Baik itu pada berkas main.js, clubs.js, ataupun data-source.js.
Mari kita ubah seluruh deklarasinya menggunakan const. Mengapa const? Karena jika kita telaah seluruh kode yang ada, tidak ada satu baris kode pun berupa statement untuk menginisialisasikan ulang nilai pada variabel. Jadi tidak ada alasan kita gunakan let pada project ini.
Setelah menerapkan const ketika deklarasi variabel, maka kode main.js, clubs.js, dan data-source.js akan tampak seperti ini:
- const main = function () {
- const searchElement = document.querySelector("#searchElement");
- const buttonSearchElement = document.querySelector("#searchButtonElement");
- const clubListElement = document.querySelector("#clubList");
- const onButtonSearchClicked = function () {
- const dataSource = new DataSource(renderResult, fallbackResult);
- dataSource.searchClub(searchElement.value);
- };
- const renderResult = function (results) {
- clubListElement.innerHTML = "";
- results.forEach(function (club) {
- const name = club.name;
- const fanArt = club.fanArt;
- const description = club.description;
- const clubElement = document.createElement("div");
- clubElement.setAttribute("class", "club");
- clubElement.innerHTML = '<img class="fan-art-club" src="' + fanArt + '" alt="Fan Art">\n' +
- '<div class="club-info">\n' +
- '<h2>' + name + '</h2>\n' +
- '<p>' + description + '</p>' +
- '</div>';
- clubListElement.appendChild(clubElement);
- })
- };
- const fallbackResult = function (message) {
- clubListElement.innerHTML = "";
- clubListElement.innerHTML += '<h2 class="placeholder">' + message + '</h2>'
- };
- buttonSearchElement.addEventListener("click", onButtonSearchClicked);
- };
- function DataSource(onSuccess, onFailed) {
- this.onSuccess = onSuccess;
- this.onFailed = onFailed;
- }
- DataSource.prototype.searchClub = function (keyword) {
- const filteredClubs = clubs.filter(function (club) {
- return club.name.toUpperCase().includes(keyword.toUpperCase());
- });
- if (filteredClubs.length) {
- this.onSuccess(filteredClubs);
- } else {
- this.onFailed(keyword + " is not found");
- }
- };
- const clubs = [
- {
- name: "Arsenal",
- stadium: "Emirates Stadium",
- fanArt: "....",
- description: "...."
- },
- {
- name: "Aston Villa",
- stadium: "Villa Park",
- fanArt: "....",
- description: "...."
- },
- {
- name: "Bournemouth",
- stadium: "Dean Court",
- fanArt: "....",
- description: "....",
- },
- {
- name: "Brighton",
- stadium: "Falmer Stadium",
- fanArt: "....",
- description: "....",
- }
- ];
Bagaimana guna memastikan perubahan yang kita lakukan sudah benar? Silakan Anda coba buka berkas index.html pada browser. Jika aplikasi berjalan dengan lancar, maka perubahan yang Anda lakukan berhasil diterapkan dengan baik.
Namun bagaimana 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/102-club-finder-variable-declaration-solution