在開始寫這篇文章之前,首先我要跟大家說一下,閉包是前端開發必考的題目,不考的話有兩個原因,第一可能出題面試官忘了,第二這家公司的面試官可能沒什么水平,
作用域和自由變數
所謂萬丈高樓平地起,盤龍臥虎高山齊,在進入閉包的學習之前,我們先要去了解一下作用域的概念,只能說真正理解作用域才能更好地學習閉包,通俗來講,作用域就是在定義的變數在某個范圍內是可使用的一個區域,

簡單地畫了個圖,上述的框框我們可以看出,其實作用域就是某個變數可使用的合法范圍,比如變數a,作為全域作用域,是公開使用的,不論是函式外部還是fn1,2,3都可以使用,就好比公廁這種地方是面向全社會人員的,我們再看看fn3,假如fn2,fn1或者函式外部需要使用或者修改a3這個變數,是無法使用的,
在這里順便講一下自由變數,自由變數就是一個變數在當前作用域沒有定義,但被使用了,我們再來看看這張圖

這個代碼段的執行順序是,先呼叫fn1()、fn2()、fn3() ,當執行fn3()的時候,返a + a1 + a2 + a3,因為在fn3()的作用域沒有a2,a1,a所以要往上一層fn2尋找,fn2沒有a1,a所以再往上一層fn1找,fn1沒有a,所以最后要到全域作用域才能找到a,因為a2,a1,a不在fn3的作用域范圍,所以它們可稱為自由變數
再啰嗦多一句,如果全域作用域都沒找到的變數,則會報錯——xx is not defined
閉包
上述的講解同學們應該可以了解到了作用域到底是神馬東西了,那么閉包這玩意,其實就是作用域的特殊情況,它有兩種表現:
1.函式作為引數傳遞
2.函式作為回傳值回傳
我們先看看兩個代碼片段
// 函式作為回傳值
function fun (){
const a = 100;
return function(){
console.log(a);//100
}
}
const fn = fun();
const a = 200;
fn();
// 函式作為引數被傳遞
function print(fn){
const a = 200;
fn();
}
const a = 100;
function fun (){
console.log(a);//100
}
print(fun);
解釋一下控制臺的列印結果,為什么是100呢,上面的內容已經講解到,自由變數往往不存在當前的作用域范圍中,所以需要一層一層地往上尋找,console.log(a)里面的變數a在函式中未被定義,所以需要往上一層尋找自己被定義和賦值的地方,
閉包的應用
我們先看一個代碼片段
// 閉包隱藏資料,只提供API
function Cache(){
// 閉包中的資料被隱藏,不被外界訪問
const data = {};
return{
set: function(key,val){
data[key] = val
},
get: function(key){
return data[key]
}
}
}
const t = Cache()
t.set('money',100)
console.log(t.get('money'));//100
上述代碼中,我們簡單做了一個Cache工具,在函式回傳值回傳兩個函式,set用于傳值,get用于取值,最后在控制臺中列印出100,那我們能不能直接修改data的值?
// 閉包隱藏資料,只提供API
function Cache(){
// 閉包中的資料被隱藏,不被外界訪問
const data = {};
return{
set: function(key,val){
data[key] = val
},
get: function(key){
return data[key]
}
}
}
data.b = 200 //控制臺會報錯
相信同學們已經知道為什么data.b = 200不可行吧,原因就是作用域問題,data是在Cache函式的作用域中,作用域外面并不能獲取到它的值,所以這里函式主要的功能是只提供API,那么閉包中的data資料則由它自己來管理,外界無法修改,
今天你學廢了嗎?

轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/344272.html
標籤:其他
上一篇:javascript中的幾種回圈
