js中的函數(shù)嵌套和閉包

今天就先和大家一起聊一聊我理解的閉包静尼。在聊這個問題之前挖炬,先了解一下變量的定義域。在js中料仗,變量定義域有全局作用域和局部作用域之說湾盗。es6中新出現(xiàn)的變量聲明關(guān)鍵字,就是為了解決部分變量作用域混亂引入的罢维。全局作用域在這就不談了淹仑。主要說說函數(shù)的作用域丙挽。一肺孵、作用域簡單一點說,函數(shù)的作用域颜阐,就是函數(shù)的花括號內(nèi)部平窘,先看兩個例子,或許能對這個概念理解的更好一點 凳怨。大家還可以關(guān)注我的微信公眾號瑰艘,蝸牛全棧是鬼。

function f1(){
  let n = 999
  console.log(n)
}
f1() // 999

function f2(){
  let n = 999
}
alert(n); // 報錯

二、函數(shù)的返回值要說閉包之前紫新,我得先說一下函數(shù)返回值均蜜。關(guān)于函數(shù)的返回值,小編也是年初才有了一個更深層次的理解芒率。沒有返回值的函數(shù)囤耳,執(zhí)行之后會返回undefined,有返回值的函數(shù)偶芍,執(zhí)行之后就變成了對應(yīng)的返回值充择。就像這樣

// 沒有返回值的函數(shù)
function f1(){
  alert(666)
}
console.log(f1()) // 出現(xiàn)彈窗之后,在控制臺輸出undefind

// 存在返回值
function f2(){
  alert(666)
  return 'over'
}
console.log(f2()) // 出現(xiàn)彈窗之后匪蟀,在控制臺輸出over椎麦。當(dāng)然,可以返回字符串材彪,也可以返回Bealon观挎,還可以返回函數(shù)。

三段化、函數(shù)嵌套
在《重構(gòu)——改善既有代碼的設(shè)計》中键兜,提出了js語法是允許函數(shù)內(nèi)部嵌套函數(shù)的,但并不是所有的編程語言都可以的穗泵,所謂代碼嵌套普气,就是在函數(shù)內(nèi)部又有函數(shù)聲明,就像這樣:

function outer(){
  let name = 'lilei'
  function inner(){
    console.log(name)
  }
} 

四佃延、閉包
前面說明了在js中的局部變量作用域的問題现诀,在實際項目中,就是需要在函數(shù)外部履肃,訪問函數(shù)內(nèi)部的變量仔沿,這個時候,按照局部變量作用域的問題尺棋。似乎是不可能的封锉,閉包的出現(xiàn),解決了這個問題膘螟。

function outer(){
  let name = 'lilei'
  function inner(){
    return name
  }
  return inner
}

上面是一個典型的閉包函數(shù)成福,在使用這個閉包函數(shù)的時候狭魂,我們可以這樣:

let g = outer()
console.log(g()) // lilei

至此笼蛛,已經(jīng)解決了在全局訪問函數(shù)內(nèi)的局部變量。但是小編在回家的路上在想翎迁,為了實現(xiàn)這個功能内斯,是不是不用這個麻煩蕴潦,我通過這樣的函數(shù)像啼,也是可以滿足需求的。

function outer(){
  let name = 'lilei'
  return name
}

console.log(outer()) // lilei  

確實上面的代碼和通過閉包最終在控制臺輸出的內(nèi)容是一樣的潭苞,那為什么還要引入閉包呢忽冻?小編也是想了接近一周才明白的,這就好比變量->函數(shù)->類此疹,每層往上都是逐步提升的過程甚颂,通過函數(shù)可以實現(xiàn)更多的邏輯,比如對數(shù)據(jù)進行處理秀菱,僅僅靠變量是不能實現(xiàn)的振诬。五、閉包的實際應(yīng)用
上面小編介紹了閉包衍菱,那么在實際項目中有什么應(yīng)用呢赶么?先看下面代碼:1、隱藏內(nèi)部變量名稱和函數(shù)執(zhí)行暫停


function outer() {
    let name = 1
    function inner() {
        return name ++
    }
    return inner
}
let g = outer()
console.log(g()) // 2
console.log(g()) // 3
console.log(g()) // 4
console.log(g()) // 5

2脊串、setTimeout函數(shù)傳遞參數(shù)
默認(rèn)的setTimeout是這樣的

圖片

小編也曾經(jīng)這樣試驗過

function f1(p) {
    console.log(p)
}
setTimeout(f1(666),3000) // 并沒有延時辫呻,直接輸出666

要想通過延時來實現(xiàn)對函數(shù)傳遞參數(shù),這時候琼锋,閉包的作用就顯現(xiàn)出來了放闺。

function f1(a) {
    function f2() {
        console.log(a);
    }
    return f2;
}
var fun = f1(1);
setTimeout(fun,1000); // 一秒之后打印出1

3、回調(diào)
  定義行為缕坎,然后把它關(guān)聯(lián)到某個用戶事件上(點擊或者按鍵)怖侦。代碼通常會作為一個回調(diào)(事件觸發(fā)時調(diào)用的函數(shù))綁定到事件。就像下面這塊代碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>測試</title>
</head>
<body>
    <a href="#" id="size-12">12</a>
    <a href="#" id="size-20">20</a>
    <a href="#" id="size-30">30</a>

    <script type="text/javascript">
        function changeSize(size){
            return function(){
                document.body.style.fontSize = size + 'px';
            };
        }

        var size12 = changeSize(12);
        var size14 = changeSize(20);
        var size16 = changeSize(30);

        document.getElementById('size-12').onclick = size12;
        document.getElementById('size-20').onclick = size14;
        document.getElementById('size-30').onclick = size16;
</script>
</body>
</html>

4谜叹、函數(shù)防抖
  在事件被觸發(fā)n秒后再執(zhí)行回調(diào)匾寝,如果在這n秒內(nèi)又被觸發(fā),則重新計時荷腊。
   實現(xiàn)的關(guān)鍵就在于setTimeout這個函數(shù)艳悔,由于還需要一個變量來保存計時,考慮維護全局純凈女仰,可以借助閉包來實現(xiàn)猜年。就像下面這樣:

/*
* fn [function] 需要防抖的函數(shù)
* delay [number] 毫秒,防抖期限值
*/
function debounce(fn,delay){
    let timer = null    //借助閉包
    return function() {
        if(timer){
            clearTimeout(timer) //進入該分支語句疾忍,說明當(dāng)前正在一個計時過程中乔外,并且又觸發(fā)了相同事件。所以要取消當(dāng)前的計時锭碳,重新開始計時
            timer = setTimeOut(fn,delay) 
        }else{
            timer = setTimeOut(fn,delay) // 進入該分支說明當(dāng)前并沒有在計時袁稽,那么就開始一個計時
        }
    }
}

六勿璃、使用類實現(xiàn)類似閉包中隱藏內(nèi)部變量功能上面是一個關(guān)于閉包的實際應(yīng)用擒抛,小編在晚上睡不著覺的時候推汽,想起同樣的需求,是不是也可以通過類來實現(xiàn)呢歧沪?最后經(jīng)過一頓折騰歹撒,答案是肯定的,就像這樣:

class Adder{
    constructor(c){
        this._c = c
    }
    increace(){
        this._c ++ 
    }
    decreace(){
        this._c --
    }
    get finalNum(){
        return this._c
    }
}
let c = new Adder(1)
c.increace()
console.log(c.finalNum) // 2
c.increace()
console.log(c.finalNum) // 3
c.increace()
console.log(c.finalNum) // 4
c.decreace()
console.log(c.finalNum) // 3

參考文章:https://www.cnblogs.com/gg-qq/p/11399152.html
https://www.cnblogs.com/pikachuworld/p/5325868.html
https://developer.mozilla.org/zh-CN/docs/Web/API/setTimeout

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末诊胞,一起剝皮案震驚了整個濱河市暖夭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌撵孤,老刑警劉巖迈着,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異邪码,居然都是意外死亡裕菠,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門闭专,熙熙樓的掌柜王于貴愁眉苦臉地迎上來奴潘,“玉大人,你說我怎么就攤上這事影钉』瑁” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵平委,是天一觀的道長奈虾。 經(jīng)常有香客問我,道長廉赔,這世上最難降的妖魔是什么愚墓? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮昂勉,結(jié)果婚禮上浪册,老公的妹妹穿的比我還像新娘。我一直安慰自己岗照,他們只是感情好村象,可當(dāng)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著攒至,像睡著了一般厚者。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上迫吐,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天库菲,我揣著相機與錄音,去河邊找鬼志膀。 笑死熙宇,一個胖子當(dāng)著我的面吹牛鳖擒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播烫止,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蒋荚,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了馆蠕?” 一聲冷哼從身側(cè)響起期升,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎互躬,沒想到半個月后播赁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡吼渡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年行拢,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诞吱。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡舟奠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出房维,到底是詐尸還是另有隱情沼瘫,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布咙俩,位于F島的核電站耿戚,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏阿趁。R本人自食惡果不足惜膜蛔,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望脖阵。 院中可真熱鬧皂股,春花似錦、人聲如沸命黔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽悍募。三九已至蘑辑,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間坠宴,已是汗流浹背洋魂。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人副砍。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓衔肢,卻偏偏與公主長得像,于是被迫代替她去往敵國和親址晕。 傳聞我的和親對象是個殘疾皇子膀懈,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容