iT邦幫忙

2021 iThome 鐵人賽

DAY 12
0
Modern Web

JavaScript 基礎修練系列 第 12

[Day12] JavaScript - 閉包 Closure

  • 分享至 

  • xImage
  •  

閉包(Closure)在MDN的解釋為: 是函式以及該函式被宣告時所在的作用域環境(lexical environment)的組合。

這樣看起來好像有聽沒有懂,比較白話文的解釋是:

  • 運作原理是呼叫 Function 內的 Function,內層 Function 作用域變數只會存在內層;
    內層 Function 變數可以不被釋放、重複使用。
  • 閉包就是存取內部的函式,優點就是能把變數隱藏在裡面讓外部存取不到。

若不使用閉包的情況:

  • 假如我們想要做一個水果的計算程式,首先針對蘋果做計算:

    var count = 0;
    function countApples() {
        count +=1;
        console.log(count + ' Apples');
    }
    
    countApples();   // 1 Apples
    countApples();   // 2 Apples
    countApples();   // 3 Apples
    
  • 接著繼續寫其他程式,寫一寫發現又需要計算橘子的數量,所以接著寫:

    var count = 0;
    function countApples() {
        count +=1;
        console.log(count + ' Apples');
    }
    
    //其他程式...
    
    var count = 0;
    function countOranges() {
        count +=1;
        console.log(count + ' Oranges');
    }
    
    countApples();   // 1 Apples
    countApples();   // 2 Apples
    countApples();   // 3 Apples
    
    countOranges();   // 4 Orange  (我們要的結果是: 1 Orange)
    countOranges();   // 5 Orange  (我們要的結果是: 2 Orange)
    countOranges();   // 6 Orange  (我們要的結果是: 3 Orange)
    
    

    當我在最後執行這兩個函式後發現,它把蘋果跟橘子的數量全部都做累加了!!!

    原因是在這段程式裡,我不小心把 count變成了 全域變數,讓程式無法辨別現在是要針對蘋果還是橘子做計算,而把它當成同一個count全部做加總。所以,這時我們就要使用閉包來解決這個問題了!

使用閉包:

  • 我們將剛剛的countApplescountOranges分別放入各自的函式appleFunc()orangeFunc()中,如此一來就可以避免count暴露在全域環境當中,count只有在appleFunc() 及 orangeFunc() 裡面才可以被存取,在函式外是無法存取的。

  • 像這樣在一個fucntion內包另一個function,並在外層函式 return 內層函式供最外層使用,通常就是使用到了閉包概念。

    function appleFunc(){
        var count = 0;
        function countApples() {          //是內部函式,是一個閉包
            count +=1;
            console.log(count + ' Apples');
        }
        return countApples
    }
    
    function orangeFunc() {
        var count = 0;
        function countOranges() {       //是內部函式,是一個閉包
            count +=1;
            console.log(count + ' Oranges');
        }
        return countOranges
    }
    
    
    var myAppleFunc = appleFunc();
    var myOrangeFunc = orangeFunc();
    
    myAppleFunc();    //1 Apples
    myOrangeFunc();   //1 Oranges
    
    myAppleFunc();    //2 Apples
    myAppleFunc();    //3 Apples
    myOrangeFunc();   //2 Oranges
    
    myOrangeFunc();   //3 Oranges
    myOrangeFunc();   //4 Oranges
    
    

  這樣就成功的讓myAppleFunc()myOrangeFunc()內的count分開計算,不互相干擾了。


/images/emoticon/emoticon07.gif

資料來源:
https://pjchender.blogspot.com/2017/05/javascript-closure.html
https://wcc723.github.io/javascript/2017/12/13/javascript-closure/


上一篇
[Day11] JavaScript - Function 函式
下一篇
[Day13] JavaScript - 函式參數 (parameters)
系列文
JavaScript 基礎修練30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言