本篇文章包懂
什么是閉包
總有人看到閉包就頭疼,因為“閉包”二字實在讓人搞不懂它的語義。但閉包其實是個很簡單的概念:閉包就是一個函數(shù),只不過這個函數(shù)有些不一樣。至于它哪里不一樣呢,可以用一句話總結出來閉包:
閉包就是一個可以訪問另一個函數(shù)作用域中的變量的函數(shù)
因為我們在編程的過程中,有時候會有“想在一個函數(shù)內部也可以訪問到另一個函數(shù)內部的變量”的需求,所以在這種情況下,閉包就應運而生了。
閉包的特性
- 函數(shù)嵌套函數(shù)
- 函數(shù)內部可以引用函數(shù)外部的參數(shù)和變量
- 參數(shù)和變量不會被垃圾回收機制回收
看不懂沒關系,先觀察以下的代碼
一個簡單的閉包
function fn1(){
var a = 1;
return function fn2(){ // fn2 就是一個閉包
alert(a);
}
}
var fn = fn1()
alert(a); // 報錯:a is not defined
fn(); // 彈出 1
這段代碼的邏輯很簡單,甚至有人在不知道什么是閉包之前自己就用過閉包。
我們來剖析一下上邊的代碼:
- 定義一個函數(shù)fn1,在函數(shù)內定義一個變量 a=1
- 在函數(shù)fn1內返回一個 fn2
- 在 fn2 內 調用 fn1 的變量 a
- 定義一個 fn ,把 fn1 的返回值 —— fn2 賦值給 fn
- 此時 fn 就是 fn2 , 執(zhí)行 fn ,成功彈出 1
通過觀察代碼我們知道, fn() 其實就是 alert(a) ,那為什么 fn() 可以成功訪問到變量 a ,而直接 alert(a) 就不行呢?——當然不行,JavaScript 的變量引用是基于由下到上,由內而外的鏈式查找的,所以外部是不能訪問到函數(shù)內定義的變量的。而閉包則替我們完成了這一點,因為閉包遵循鏈式查找的法則,而且基于它的特性:閉包訪問到的參數(shù)和變量不會被垃圾回收機制回收,我們就成功的實現(xiàn)了在外部訪問函數(shù)內部的變量。
讀到這里,你已經(jīng)精通閉包了。
使用閉包的優(yōu)越性
- 將函數(shù)內部變量進行封裝,保證內部變量的私有化,外部無法直接訪問。
- 避免了命名沖突。
- 將這個變量長期駐扎在內存之中,不會被銷毀。(這一點要合理使用,如果過多的使用閉包會造成內存消耗過多)
稍后更新閉包的使用場景,等一個催更...