看了網上很多介紹閉包的文章,始終無法明白閉包
TMD到底是什么?直到下面2篇文章,解決了我的疑惑,在此,先上鏈接:
閉包是什么?它能幫我們解決什么問題?
在回答上面的問題之前,先扯點其他的廢話!早在ES6
之前,JS并不存在塊級作用域(這有別于Java
、C++
等傳統面向對象語言),舉個通俗的例子:
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
,導致它無法被釋放,一直被保存在內存中。
也就是上面所說的持久保存。
應用
- 暫存數據(上面所提)
- 模擬私有變量
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.
好啦,這就是我現階段對于閉包的理解,有可能理解的還不夠深刻,有問題歡迎各位拍磚指正!