Closure dalam TypeScript
Dalam artikel ini, kami akan menerangkan tentang closure dalam TypeScript.
YouTube Video
Closure dalam TypeScript
Apakah itu Closure?
Closure merujuk kepada keupayaan untuk mengekalkan rujukan kepada skop (persekitaran) di mana fungsi itu telah ditakrifkan, walaupun fungsi itu dipanggil di luar skop tersebut. Di bawah, closure akan diterangkan termasuk penjelasan jenis (type annotation).
Secara ringkas, closure menggabungkan satu fungsi dan persekitaran pembolehubah di mana fungsi itu ditakrifkan, membolehkan akses kepada persekitaran itu apabila fungsi dipanggil.
Mekanisme Asas Closure
Dalam TypeScript, apabila satu fungsi ditakrifkan di dalam fungsi lain, adalah jelas bahawa fungsi dalaman boleh mengakses pembolehubah fungsi luaran. Berikut adalah contoh asas closure dengan penanda jenis.
1function outerFunction(): () => void {
2 let outerVariable: string = "I am from outer function";
3
4 function innerFunction(): void {
5 // The inner function accesses the variable of the outer function
6 console.log(outerVariable);
7 }
8
9 return innerFunction;
10}
11
12const closure: () => void = outerFunction();
13closure(); // "I am from outer function"
outerFunction
memulangkan fungsi dalamaninnerFunction
.innerFunction
memaparkan nilai pembolehubahouterVariable
fungsi luaran.
Kegunaan dan Kelebihan Closure
Closure Data (Penyembunyian Data)
Di bawah adalah contoh closure dengan penanda jenis untuk tujuan penyembunyian (enkapsulasi) data.
1function createCounter(): () => number {
2 let count: number = 0;
3
4 return function (): number {
5 count += 1;
6 return count;
7 };
8}
9
10const counter: () => number = createCounter();
11console.log(counter()); // 1
12console.log(counter()); // 2
13console.log(counter()); // 3
createCounter
memulangkan fungsi yang memulangkan nilai jenisnumber
.- Pembolehubah
count
ditakrifkan dengan jenisnumber
dan dimanipulasi dalam closure.
Fungsi Tertib Tinggi
Closure sangat berguna ketika mencipta fungsi tertib tinggi. Di sini, fungsi aras tinggi ialah fungsi yang mengambil fungsi lain sebagai argumen atau mengembalikan fungsi sebagai hasilnya. Berikut adalah contoh fungsi tertib tinggi disertai penanda jenis yang jelas.
1function createMultiplier(multiplier: number): (value: number) => number {
2 return function (value: number): number {
3 return value * multiplier;
4 };
5}
6
7const double: (value: number) => number = createMultiplier(2);
8console.log(double(5)); // 10
9
10const triple: (value: number) => number = createMultiplier(3);
11console.log(triple(5)); // 15
createMultiplier
ialah fungsi aras tinggi yang mencipta fungsi untuk mendarab dengan nombor yang diterima sebagai argumen.- Fungsi pendaraban dalaman juga mengambil nombor dan mengembalikan hasil pendaraban sebagai nombor.
Contoh Pelaksanaan Closure dalam TypeScript
Mari kita lihat juga contoh melaksanakan penjejak kiraan berdasarkan julat sebagai penutupan.
1function rangeCounter(min: number, max: number): () => number | string {
2 let count: number = min;
3
4 return function (): number | string {
5 if (count <= max) {
6 return count++;
7 } else {
8 return `Count has exceeded the maximum value: ${max}`;
9 }
10 };
11}
12
13const counter: () => number | string = rangeCounter(1, 5);
14
15console.log(counter()); // 1
16console.log(counter()); // 2
17console.log(counter()); // 3
18console.log(counter()); // 4
19console.log(counter()); // 5
20console.log(counter()); // "Count has exceeded the maximum value: 5"
- Fungsi
rangeCounter
memulangkan satu fungsi yang akan memulangkan sama adanumber
ataustring
. - Dalam fungsi dalaman, jika
count
melebihimax
, ia akan memulangkan mesej jenisstring
; jika tidak, ia memulangkan jenisnumber
.
Langkah Berjaga-jaga Ketika Menggunakan Closure
Potensi Kebocoran Memori daripada Closure
Closure boleh mengekalkan pembolehubah dari skop luar, yang kadang-kadang boleh menyebabkan kebocoran memori. Closure yang tidak diperlukan perlu dilepaskan dari memori secara eksplisit.
1function createLeak(): () => void {
2 // Large array consuming significant memory
3 const largeArray: string[] = new Array(1000000).fill("leak");
4
5 // Closure capturing `largeArray`
6 return function (): void {
7 console.log(largeArray[0]); // Using the captured array
8 };
9}
10
11// Create a closure that holds a reference to the large array
12let leakyFunction = createLeak();
13
14// The large array is not released as `leakyFunction` still references it
15
16// When the object is no longer needed
17leakyFunction = null; // Explicitly remove the reference
- Dalam kod ini,
largeArray
yang dicipta di dalamcreateLeak
sepatutnya dilepaskan apabila ia keluar dari skop, tetapi tidak kerana closure telah menangkap (capture)largeArray
. SelagileakyFunction
wujud, memori yang tidak diperlukan ini akan terus dikekalkan. - Apabila objek atau pembolehubah tidak diperlukan lagi, menetapkan rujukannya kepada
null
membolehkan pengumpul sampah (garbage collector) mengesannya dan melepaskan memori.
Penyalahgunaan Closure dalam Gelung (Loop)
Apabila mencipta closure di dalam satu gelung, mungkin timbul masalah merujuk kepada pembolehubah yang sama. Contoh berikut menunjukkan kes di mana pembolehubah i
yang diisytiharkan dengan var
tidak berfungsi dengan betul.
1for (var i: number = 0; i < 3; i++) {
2 setTimeout((): void => {
3 console.log(i);
4 }, 1000);
5}
6// Output: 3, 3, 3
Kod ini tidak memberikan hasil yang diinginkan kerana i
merujuk kepada nilai 3 di penghujung gelung. Untuk membetulkan situasi ini, gunakan let
untuk memisahkan skop atau gunakan fungsi yang dipanggil serta-merta (immediately-invoked function).
1for (let i: number = 0; i < 3; i++) {
2 setTimeout((): void => {
3 console.log(i);
4 }, 1000);
5}
6// Output: 0, 1, 2
Dengan menggunakan let
, skop untuk i
dipisahkan untuk setiap iterasi gelung, lalu memberikan hasil yang dijangkakan.
Ringkasan
Dalam TypeScript, closure boleh menghasilkan kod yang lebih selamat dan boleh dijangka dengan memanfaatkan sistem jenis. Penggunaan closure yang betul membolehkan enkapsulasi data dan reka bentuk fungsi tertib tinggi yang fleksibel. Selain itu, perhatian harus diberikan dalam pengurusan memori dan rujukan skop yang tidak sengaja ketika menggunakan closure.
Anda boleh mengikuti artikel di atas menggunakan Visual Studio Code di saluran YouTube kami. Sila lihat juga saluran YouTube kami.