看了網(wǎng)上很多介紹閉包的文章麦乞,始終無法明白閉包
TMD到底是什么蹂随?直到下面2篇文章茁帽,解決了我的疑惑掉冶,在此,先上鏈接:
閉包是什么厌小?它能幫我們解決什么問題?
在回答上面的問題之前战秋,先扯點其他的廢話璧亚!早在ES6
之前,JS并不存在塊級作用域(這有別于Java
、C++
等傳統(tǒng)面向?qū)ο笳Z言),舉個通俗的例子:
for(var i = 0; i < 5; i++) {
}
console.log(i); // 循環(huán)結(jié)束癣蟋,外部可以訪問變量i的值透硝,輸出5
但是,有一種情況例外,那就是函數(shù)
,同樣上例子:
function demo() {
var local = 100;
// TODO...
}
很顯然疯搅,我們在外部是無法訪問函數(shù)內(nèi)部的變量local
的濒生。那如果說,我們就是想訪問函數(shù)內(nèi)部的某個變量幔欧,是否有方案可行呢罪治?
答案就是利用JS的作用域鏈實現(xiàn)
。先對作用域鏈簡單總結(jié)一下:
- 子執(zhí)行環(huán)境可以訪問父執(zhí)行環(huán)境中的變量礁蔗。若當前執(zhí)行環(huán)境不存在某個變量觉义,就會逐級向上面的父執(zhí)行環(huán)境查找,找到浴井,則停止向上搜索;否則晒骇,返回
undefined
。 - 外部執(zhí)行環(huán)境無法訪問其子執(zhí)行環(huán)境中的變量磺浙。
既然內(nèi)部函數(shù)可以訪問外部函數(shù)的變量洪囤,那我們就可以在函數(shù)demo
內(nèi)部定義一個函數(shù),返回該變量撕氧,并將整個函數(shù)返回就可以達到我們的目的了瘤缩。(說的不是很清楚,上代碼)
function demo() {
var local = 100;
return function() {
return local;
}
}
var fn = demo();
var result = fn();
// result = 100
是不是So Easy:遣堋!何暮!扯了這么多廢話奄喂,終于到我們的正題了!其實海洼,我們在不知不覺中已經(jīng)構(gòu)建了一個閉包跨新。
對于閉包
的定義,并沒有一個統(tǒng)一說法坏逢。在我看來域帐,閉包就是一種機制,它可以用來訪問函數(shù)內(nèi)部的局部變量是整,并且可以持久擁有它肖揣!
訪問函數(shù)內(nèi)部的局部變量
我們上面介紹過了,持久擁有
是啥玩意浮入?是不是覺得很抽象龙优?!那讓我們一起分析一下上面的代碼事秀。
通常彤断,調(diào)用一個函數(shù)野舶,當調(diào)用完后,其執(zhí)行環(huán)境就會被銷毀,其內(nèi)部的局部變量等(活動對象)也會一起被瀏覽器的垃圾回收機制回收宰衙。但是平道,函數(shù)fn
所指向的匿名函數(shù)中(執(zhí)行環(huán)境)并沒有變量local
,它取的是父執(zhí)行環(huán)境中的local
,導致它無法被釋放供炼,一直被保存在內(nèi)存中一屋。
也就是上面所說的持久保存。
應(yīng)用
- 暫存數(shù)據(jù)(上面所提)
- 模擬私有變量
var Car = (function() {
var speed = 0;
return {
setSpeed: function(num) {
speed = num;
},
getSpeed: function() {
return speed;
}
}
})();
總結(jié)
編程界崇尚以簡潔優(yōu)雅為美劲蜻,很多時候如果你覺得一個概念很復(fù)雜陆淀,那么很可能是你理解錯了。
If everything seems completely unclear then the best thing to do is to play with the examples.
好啦先嬉,這就是我現(xiàn)階段對于閉包的理解轧苫,有可能理解的還不夠深刻,有問題歡迎各位拍磚指正疫蔓!