iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 19
1
自我挑戰組

JavaScript技術手冊閱讀筆記系列 第 19

第19天:Closure閉包

  • 分享至 

  • xImage
  •  

Closure這名詞是函式與作用域環境的組合,作用域環境指的是在存取變數時,決定如何使用哪個變數的環境。

例如我們在函式中宣告一個區域函式如下

function test(){
    let b =1;
    
    function g(i){
        return i+b;
    }
    return g;
}

let f = test();

console.log(f(1));
console.log(f(2));

https://ithelp.ithome.com.tw/upload/images/20201004/20120420QapMLcCp2y.png

let f = test()執行完之後應該會拿到g函式,可是g函式裡面的b的變數是test裡面所提供的,但我們執行f(1)時,理論上應該只是執行g函式,但我們沒有b變數,在執行i+b應該會發生錯誤才對,但是沒有發生任何問題,程式成功執行,並且拿到1+1=2的結果。

以上的原因是JavaScript會很自然地建立閉包,g函式會用到test裡面的b變數,所以JavaScript會很自然的幫g函式打包保留b變數。

不過事後若b變數的值改變了,那就會改變到我們f(1)的結果。

例如下圖,我們跑回圈將匿名函式指派進farr陣列的元素裡,明明有照順序傳入0、1、2,可是最後再使用一次全部都是拿到3,這是因為被打包進匿名函式的i變數最後被改變為3。
https://ithelp.ithome.com.tw/upload/images/20201004/20120420i9oiN7ClL2.png

如果希望1是1,2是2,不會因為變數的改變而影響結果的話,在ES6以前,只能使用函式傳值的方式產生新變數。

function g(i){
    function gg(){
        return i;
    }
    return gg;
}

https://ithelp.ithome.com.tw/upload/images/20201004/20120420GlYPKOZarE.png

而在ES6後,在for迴圈中的var改用let的宣告方式時,每跑一次迴圈執行JavaScript背後會幫let產生新的執行環境偷偷產生新變數,這樣就不會有我們事後執行farr[1]();結果值不如預期的問題。
https://ithelp.ithome.com.tw/upload/images/20201005/20120420eXwdtgOP92.png


上一篇
第18天:箭頭函式
下一篇
第20天:還在對字串用for迴圈嗎?改用for...of吧,for...of與for...in的差別
系列文
JavaScript技術手冊閱讀筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言