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"
- Jenis pulangan bagi
outerFunction
ialah() => void
, menunjukkan bahawa ia memulangkan satu fungsi. - Jenis bagi
innerFunction
dinyatakan secara eksplisit sebagaivoid
, menunjukkan ia tidak mempunyai nilai pulangan.
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
- Fungsi
createCounter
memulangkan satu fungsi dengan jenis() => number
. - Pembolehubah
count
ditakrifkan dengan jenisnumber
dan dimanipulasi dalam closure.
Fungsi Tertib Tinggi
Closure sangat berguna ketika mencipta fungsi tertib tinggi. 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
menerima argumen jenisnumber
dan memulangkan satu fungsi dengan jenis(value: number) => number
.- Fungsi dalaman juga menerima
value
sebagai jenisnumber
dan memulangkan hasil sebagai jenisnumber
.
Contoh Pelaksanaan Closure dalam TypeScript
Laksanakan kaunter dengan had julat sebagai closure dengan penanda jenis ditambah.
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 situasi di mana pembolehubah i
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.