Artikel ini untuk memahami skrip lama
Informasi dalam artikel ini berguna untuk memahami skrip lama.
Itu bukan cara kami menulis kode baru.
Pada bab pertama tentang variabel, kami telah menyebutkan tiga cara deklarasi variabel:
let
const
var
Deklarasi var
mirip dengan let
. Seringkali kita dapat mengganti let
dengan var
atau sebaliknya dan mengharapkan semuanya berfungsi:
var pesan = "Hai"; peringatan (pesan); // Hai
Namun secara internal, var
adalah binatang yang sangat berbeda, yang berasal dari masa lalu. Ini umumnya tidak digunakan dalam skrip modern, tetapi masih tersembunyi di skrip lama.
Jika Anda tidak berencana untuk memenuhi skrip seperti itu, Anda mungkin melewatkan bab ini atau menundanya.
Di sisi lain, penting untuk memahami perbedaan saat memigrasikan skrip lama dari var
ke let
, untuk menghindari kesalahan ganjil.
Variabel, yang dideklarasikan dengan var
, memiliki cakupan fungsi atau cakupan global. Mereka terlihat melalui blok.
Misalnya:
jika (benar) { var tes = benar; // gunakan "var" daripada "biarkan" } peringatan(tes); // benar, variabel berada setelah if
Karena var
mengabaikan blok kode, kita mendapatkan variabel global test
.
Jika kita menggunakan let test
alih-alih var test
, maka variabel hanya akan terlihat di dalam if
:
jika (benar) { biarkan tes = benar; // gunakan "biarkan" } peringatan(tes); //ReferenceError: pengujian tidak ditentukan
Hal yang sama untuk loop: var
tidak boleh berupa blok atau loop-lokal:
untuk (var saya = 0; saya < 10; saya++) { var satu = 1; // ... } peringatan(i); // 10, "i" terlihat setelah loop, ini adalah variabel global peringatan(satu); // 1, "satu" terlihat setelah loop, itu adalah variabel global
Jika blok kode berada di dalam suatu fungsi, maka var
menjadi variabel tingkat fungsi:
fungsi ucapkan Hai() { jika (benar) { var frase = "Halo"; } peringatan(frasa); // berhasil } sayHai(); peringatan(frasa); //ReferenceError: frasa tidak ditentukan
Seperti yang bisa kita lihat, var
menembus if
, for
atau blok kode lainnya. Itu karena dahulu kala di JavaScript, blok tidak memiliki Lingkungan Leksikal, dan var
merupakan sisa dari lingkungan tersebut.
Jika kita mendeklarasikan variabel yang sama dengan let
dua kali dalam lingkup yang sama, itu adalah kesalahan:
biarkan pengguna; biarkan pengguna; // SyntaxError: 'pengguna' telah dideklarasikan
Dengan var
, kita dapat mendeklarasikan ulang suatu variabel berapa kali pun. Jika kita menggunakan var
dengan variabel yang sudah dideklarasikan, maka variabel tersebut akan diabaikan:
var pengguna = "Pete"; var pengguna = "John"; // "var" ini tidak melakukan apa pun (sudah dideklarasikan) // ...itu tidak memicu kesalahan peringatan(pengguna); // Yohanes
Deklarasi var
diproses ketika fungsi dimulai (atau skrip dimulai untuk global).
Dengan kata lain, variabel var
didefinisikan dari awal fungsi, di mana pun definisinya berada (dengan asumsi definisi tersebut tidak ada dalam fungsi bersarang).
Jadi kode ini:
fungsi ucapkan Hai() { frase = "Halo"; peringatan(frasa); frase var; } sayHai();
…Secara teknis sama dengan ini (memindahkan var phrase
ke atas):
fungsi ucapkan Hai() { frase var; frase = "Halo"; peringatan(frasa); } sayHai();
…Atau bahkan seperti ini (ingat, blok kode diabaikan):
fungsi ucapkan Hai() { frase = "Halo"; // (*) jika (salah) { frase var; } peringatan(frasa); } sayHai();
Orang juga menyebut perilaku seperti itu “mengangkat” (menaikkan), karena semua var
“diangkat” (diangkat) ke atas fungsi.
Jadi pada contoh di atas, cabang if (false)
tidak pernah dijalankan, tapi itu tidak masalah. var
di dalamnya diproses di awal fungsi, jadi pada saat (*)
variabel tersebut ada.
Deklarasi diangkat, namun penugasan tidak.
Hal ini paling baik ditunjukkan dengan sebuah contoh:
fungsi ucapkan Hai() { peringatan(frasa); var frase = "Halo"; } sayHai();
Baris var phrase = "Hello"
memiliki dua tindakan di dalamnya:
Deklarasi variabel var
Penugasan variabel =
.
Deklarasi diproses pada awal eksekusi fungsi (“diangkat”), namun penugasan selalu berfungsi di tempat kemunculannya. Jadi kodenya pada dasarnya berfungsi seperti ini:
fungsi ucapkan Hai() { frasa var; // deklarasi berfungsi di awal... peringatan(frasa); // belum diartikan frase = "Halo"; // ...tugas - saat eksekusi mencapainya. } sayHai();
Karena semua deklarasi var
diproses pada awal fungsi, kita dapat mereferensikannya di mana saja. Tetapi variabel tidak terdefinisi hingga penugasan.
Dalam kedua contoh di atas, alert
berjalan tanpa kesalahan, karena variabel phrase
ada. Namun nilainya belum ditetapkan, sehingga menunjukkan undefined
.
Di masa lalu, karena hanya ada var
, dan tidak memiliki visibilitas tingkat blok, pemrogram menemukan cara untuk menirunya. Apa yang mereka lakukan disebut “ekspresi fungsi yang segera dipanggil” (disingkat IIFE).
Itu bukan sesuatu yang harus kita gunakan saat ini, tapi Anda dapat menemukannya di skrip lama.
IIFE terlihat seperti ini:
(fungsi() { var pesan = "Halo"; peringatan (pesan); // Halo })();
Di sini, Ekspresi Fungsi dibuat dan segera dipanggil. Jadi kodenya langsung dieksekusi dan memiliki variabel pribadinya sendiri.
Ekspresi Fungsi dibungkus dengan tanda kurung (function {...})
, karena ketika mesin JavaScript menemukan "function"
dalam kode utama, ia memahaminya sebagai awal Deklarasi Fungsi. Namun Deklarasi Fungsi harus mempunyai nama, sehingga kode seperti ini akan memberikan error:
// Mencoba mendeklarasikan dan segera memanggil suatu fungsi function() { // <-- SyntaxError: Pernyataan fungsi memerlukan nama fungsi var pesan = "Halo"; peringatan (pesan); // Halo }();
Meskipun kita mengatakan: “oke, ayo tambahkan nama”, itu tidak akan berhasil, karena JavaScript tidak mengizinkan Deklarasi Fungsi untuk segera dipanggil:
// kesalahan sintaksis karena tanda kurung di bawah fungsi pergi() { }(); // <-- tidak dapat langsung memanggil Deklarasi Fungsi
Jadi, tanda kurung di sekitar fungsi adalah trik untuk menunjukkan JavaScript bahwa fungsi tersebut dibuat dalam konteks ekspresi lain, dan karenanya merupakan Ekspresi Fungsi: tidak memerlukan nama dan dapat langsung dipanggil.
Ada cara lain selain tanda kurung untuk memberi tahu JavaScript bahwa yang kami maksud adalah Ekspresi Fungsi:
// Cara membuat IIFE (fungsi() { alert("Tanda kurung di sekitar fungsi"); })(); (fungsi() { alert("Tanda kurung di sekeliling semuanya"); }()); !fungsi() { alert("Operator Bitwise NOT memulai ekspresi"); }(); +fungsi() { alert("Unary plus memulai ekspresi"); }();
Dalam semua kasus di atas kita mendeklarasikan Ekspresi Fungsi dan segera menjalankannya. Mari kita perhatikan lagi: saat ini tidak ada alasan untuk menulis kode seperti itu.
Ada dua perbedaan utama var
dibandingkan dengan let/const
:
Variabel var
tidak memiliki cakupan blok, visibilitasnya terbatas pada fungsi saat ini, atau global, jika dideklarasikan di luar fungsi.
Deklarasi var
diproses pada saat fungsi dimulai (skrip dimulai untuk global).
Ada satu lagi perbedaan kecil terkait objek global, yang akan kita bahas di bab berikutnya.
Perbedaan-perbedaan ini sering kali membuat var
menjadi lebih buruk daripada let
. Variabel tingkat blok adalah hal yang hebat. Itu sebabnya let
diperkenalkan dalam standar sejak lama, dan sekarang menjadi cara utama (bersama dengan const
) untuk mendeklarasikan sebuah variabel.