對閉包如何理解
要想了解閉包潦嘶,首先看一下變量作用域抵怎。
一各谚、變量的作用域莺债。
變量的作用域有兩種:全局變量和局部變量滋觉。
Javascript語言的特殊之處
函數(shù)內(nèi)部可以直接讀取全局變量签夭。在函數(shù)外部自然無法讀取函數(shù)內(nèi)的局部變量。
這里需要注意椎侠,函數(shù)內(nèi)部聲明變量的時候第租,一定要使用var命令。如果不用的話我纪,實際上聲明了一個全局變量慎宾!
那么如何從外部讀取局部變量?
正常情況下浅悉,這是辦不到的趟据,只有通過變通方法才能實現(xiàn)。那就是在函數(shù)的內(nèi)部术健,再定義一個函數(shù)之宿。
這就是Javascript語言特有的“鏈式作用域”結(jié)構(gòu):子對象會一級一級地向上尋找所有父對象的變量。所以苛坚,父對象的所有變量,對子對象都是可見的色难,反之則不成立泼舱。
function fn1(){
n=666;
function fn2(){
alert(n);
}
return fn2;
}
var result=fn1();
result(); // 666
二、閉包的概念
包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)枷莉。
由于在Javascript語言中娇昙,只有函數(shù)內(nèi)部的子函數(shù)才能讀取局部變量,因此可以把閉包簡單理解成“定義在一個函數(shù)內(nèi)部的函數(shù)”笤妙。
所以冒掌,在本質(zhì)上,閉包就是將函數(shù)內(nèi)部和函數(shù)外部連接起來的一座橋梁蹲盘。
或者換句話說股毫,子函數(shù)可以使用父函數(shù)的局部變量。
function show() {
var a=12;
function show1(){
alert(a);
}
show1();
}
show();
閉包更普遍的一種理解方式:
其實召衔,很多函數(shù)都存在閉包铃诬,廣義的講,所有函數(shù)都可以是閉包苍凛;
以下兩種方式都可以形成閉包趣席。
(function(){
封閉空間
})()
{
let //es6的定義變量的一種用法
}
閉包另一種更嚴格的理解方式(詞法環(huán)境)。
閉包由函數(shù)和與其相關(guān)的引用環(huán)境的組合而成
閉包允許函數(shù)訪問其引用環(huán)境中的變量(又稱自由變量)
廣義上來說醇蝴,所有 JavaScript 的函數(shù)都可以成為閉包宣肚,因為 JavaScript 函數(shù)在創(chuàng)建時保存了當(dāng)前的詞法環(huán)境。
function add() {
var i = 0;
return function() {
alert(i++);
}
}
var f = add();
f();
f();
三悠栓、閉包擴展延伸:
1霉涨、Js代碼:
function outerFun()
{
var a=0;
function innerFun()
{
a++;
alert(a);
}
return innerFun; //注意這里
}
var obj=outerFun();
obj(); //結(jié)果為1
obj(); //結(jié)果為2 注意這里說明變量在內(nèi)存不會被 釋放,因為閉包需要它們
var obj2=outerFun();
obj2(); //結(jié)果為1
obj2(); //結(jié)果為2 注意這里說明變量在內(nèi)存不會被釋放,因為閉包需要它們
** 什么是閉包:**
當(dāng)內(nèi)部函數(shù) 在定義它的作用域 的外部被引用時,就創(chuàng)建了該內(nèi)部函數(shù)的閉包 ,
如果內(nèi)部函數(shù)引用了位于外部函數(shù)的變量,當(dāng)外部函數(shù)調(diào)用完畢后,這些變量在內(nèi)存不會被 釋放,因為閉包需要它們.
2按价、Js代碼:
var a=13;
function show(){
var a=5;
alert(a);
}
show(); //結(jié)果 5
alert(a); //結(jié)果 13
遮蔽
當(dāng)函數(shù)內(nèi)部和外部同時定義一個變量時,這是兩者雖然名字相同嵌纲,但作用域不同俘枫,沒有毛線關(guān)系,既不會發(fā)生閉包也不會產(chǎn)生聯(lián)系逮走,這是遮蔽鸠蚪。
3、Js代碼:
function outerFun()
{
var a =0;
alert(a);
}
var a=4;
outerFun();
alert(a);
結(jié)果是 0 , 4 .
因為在函數(shù)內(nèi)部使用了var關(guān)鍵字 維護a的作用域在outFun()內(nèi)部.
4师溅、再看下面的代碼:
function outerFun()
{
//沒有var
a =0;
alert(a);
}
var a=4;
outerFun();
alert(a);
結(jié)果為 0 , 0 真是奇怪,為什么呢?
作用域鏈是描述一種路徑的術(shù)語,沿著該路徑可以確定變量的值 .
當(dāng)執(zhí)行a=0時,因為沒有使用var關(guān)鍵字,因此賦值操作會沿著作用域鏈到var a=4; 并改變其值茅信。