Bagaimana cara kerja “JavaScript closures”?

Bagaimana cara kerja “JavaScript closures”?

iis

September 11, 2019

closures bukanlah sihir

Halaman ini menjelaskan tentang penutupan sehingga programmer dapat memahaminya – menggunakan kode JavaScript yang berfungsi. Ini bukan untuk guru atau programmer fungsional.

Penutupan tidak sulit untuk dipahami begitu konsep inti dikuasai. Namun, mereka tidak mungkin dipahami dengan membaca penjelasan teoretis atau berorientasi akademis!

javascript-illustration

Artikel ini ditujukan untuk pemrogram dengan beberapa pengalaman pemrograman dalam bahasa utama, dan yang dapat membaca fungsi JavaScript berikut:

function sayHello(name) {
var text = 'Hello ' + name;
var say = function() { console.log(text); }
say();
}
sayHello('Joe');

Dua ringkasan singkat

Ketika suatu fungsi (foo) mendeklarasikan fungsi lain (bar dan baz), keluarga variabel lokal yang dibuat di foo tidak dimusnahkan ketika fungsi keluar. Variabel hanya menjadi tidak terlihat oleh dunia luar. Karena itu foo dapat secara cerdik mengembalikan fungsi bar dan baz, dan mereka dapat terus membaca, menulis, dan berkomunikasi satu sama lain melalui keluarga variabel tertutup ini (“penutupan”) yang tidak dapat dicoba oleh siapa pun, bahkan oleh seseorang yang memanggil foo lagi di masa depan.

Penutupan adalah salah satu cara untuk mendukung fungsi kelas satu; itu adalah ekspresi yang dapat mereferensikan variabel dalam ruang lingkupnya (ketika pertama kali dinyatakan), ditugaskan ke variabel, diteruskan sebagai argumen ke suatu fungsi, atau dikembalikan sebagai hasil fungsi.

Contoh closures

Kode berikut mengembalikan referensi ke fungsi:

function sayHello2(name) {
var text = 'Hello ' + name; // Local variable
var say = function() { console.log(text); }
return say;
}
var say2 = sayHello2('Bob');
say2(); // logs "Hello Bob"

Sebagian besar programmer JavaScript akan memahami bagaimana referensi ke suatu fungsi dikembalikan ke variabel (say2) dalam kode di atas. Jika tidak, maka Anda perlu melihatnya sebelum dapat mempelajari penutupan. Seorang programmer yang menggunakan C akan menganggap fungsinya sebagai mengembalikan sebuah pointer ke suatu fungsi, dan bahwa variabel mengatakan dan berkata2 masing-masing adalah sebuah pointer ke suatu fungsi.

Ada perbedaan kritis antara pointer C ke suatu fungsi dan referensi JavaScript ke suatu fungsi. Dalam JavaScript, Anda dapat menganggap variabel referensi fungsi memiliki penunjuk baik untuk fungsi maupun penunjuk tersembunyi ke penutupan.

Kode di atas memiliki penutup karena fungsi fungsi anonim () {console.log (teks); } dideklarasikan di dalam fungsi lain, sayHello2 () dalam contoh ini. Dalam JavaScript, jika Anda menggunakan kata kunci fungsi di dalam fungsi lain, Anda sedang membuat penutupan.

Dalam C dan sebagian besar bahasa umum lainnya, setelah suatu fungsi kembali, semua variabel lokal tidak lagi dapat diakses karena stack-frame dihancurkan.

Dalam JavaScript, jika Anda mendeklarasikan suatu fungsi di dalam fungsi lain, maka variabel lokal dari fungsi luar tetap dapat diakses setelah kembali darinya. Ini ditunjukkan di atas, karena kami memanggil fungsi say2 () setelah kami kembali dari sayHello2 (). Perhatikan bahwa kode yang kita sebut referensi teks variabel, yang merupakan variabel lokal dari fungsi sayHello2 ().

function() { console.log(text); } // Output of say2.toString();

Melihat output dari say2.toString (), kita dapat melihat bahwa kode tersebut merujuk ke teks variabel. Fungsi anonim dapat merujuk teks yang memegang nilai ‘Hello Bob’ karena variabel lokal sayHello2 () telah diam-diam tetap hidup dalam penutupan.

Jeniusnya adalah bahwa dalam JavaScript referensi fungsi juga memiliki referensi rahasia untuk penutupan yang dibuat – mirip dengan bagaimana delegasi adalah penunjuk metode ditambah referensi rahasia ke objek.
Lebih banyak contoh

Untuk beberapa alasan, penutupan tampaknya sangat sulit untuk dipahami ketika Anda membaca tentang mereka, tetapi ketika Anda melihat beberapa contoh, menjadi jelas bagaimana cara kerjanya (butuh beberapa saat bagi saya). Saya sarankan bekerja melalui contoh-contoh dengan hati-hati sampai Anda mengerti bagaimana mereka bekerja. Jika Anda mulai menggunakan penutupan tanpa sepenuhnya memahami cara kerjanya, Anda akan segera membuat beberapa bug yang sangat aneh!
Contoh 3

Contoh ini menunjukkan bahwa variabel lokal tidak disalin – mereka disimpan oleh referensi. Seolah-olah tumpukan-bingkai tetap hidup dalam memori bahkan setelah fungsi luar keluar!

function say667() {
// Local variable that ends up within closure
var num = 42;
var say = function() { console.log(num); }
num++;
return say;
}
var sayNumber = say667();
sayNumber(); // logs 43