JS學習筆記之閉包

看了網上很多介紹閉包的文章,始終無法明白閉包TMD到底是什么?直到下面2篇文章,解決了我的疑惑,在此,先上鏈接:

  1. How do JavaScript closures work?
  2. JS 中的閉包是什么?

閉包是什么?它能幫我們解決什么問題?

在回答上面的問題之前,先扯點其他的廢話!早在ES6之前,JS并不存在塊級作用域(這有別于JavaC++等傳統面向對象語言),舉個通俗的例子:

for(var i = 0; i < 5; i++) {
}
console.log(i);    // 循環結束,外部可以訪問變量i的值,輸出5

但是,有一種情況例外,那就是函數,同樣上例子:

function demo() {
  var local = 100;
  // TODO...
}

很顯然,我們在外部是無法訪問函數內部的變量local的。那如果說,我們就是想訪問函數內部的某個變量,是否有方案可行呢?

答案就是利用JS的作用域鏈實現。先對作用域鏈簡單總結一下:

  • 子執行環境可以訪問父執行環境中的變量。若當前執行環境不存在某個變量,就會逐級向上面的父執行環境查找,找到,則停止向上搜索;否則,返回undefined
  • 外部執行環境無法訪問其子執行環境中的變量。

既然內部函數可以訪問外部函數的變量,那我們就可以在函數demo內部定義一個函數,返回該變量,并將整個函數返回就可以達到我們的目的了。(說的不是很清楚,上代碼)

function demo() {
  var local = 100;
  return function() {
    return local;
  }
}
var fn = demo();
var result = fn();
// result = 100

是不是So Easy!!!扯了這么多廢話,終于到我們的正題了!其實,我們在不知不覺中已經構建了一個閉包。

對于閉包的定義,并沒有一個統一說法。在我看來,閉包就是一種機制,它可以用來訪問函數內部的局部變量,并且可以持久擁有它!

訪問函數內部的局部變量我們上面介紹過了,持久擁有是啥玩意?是不是覺得很抽象?!那讓我們一起分析一下上面的代碼。

通常,調用一個函數,當調用完后,其執行環境就會被銷毀,其內部的局部變量等(活動對象)也會一起被瀏覽器的垃圾回收機制回收。但是,函數fn所指向的匿名函數中(執行環境)并沒有變量local,它取的是父執行環境中的local,導致它無法被釋放,一直被保存在內存中。
也就是上面所說的持久保存

應用

  1. 暫存數據(上面所提)
  2. 模擬私有變量
var Car = (function() {
    var speed = 0;
    return {
        setSpeed: function(num) {
            speed = num;
        },
        getSpeed: function() {
            return speed;
        }
    }
})();

總結

編程界崇尚以簡潔優雅為美,很多時候如果你覺得一個概念很復雜,那么很可能是你理解錯了。

If everything seems completely unclear then the best thing to do is to play with the examples.

好啦,這就是我現階段對于閉包的理解,有可能理解的還不夠深刻,有問題歡迎各位拍磚指正!

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容