一高蜂、閉包定義:
閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)沥匈≌嵛梗—— 阮一峰
只要有一個(gè)函數(shù)使用了它外面的變量,這個(gè)函數(shù)就是一個(gè)閉包高帖。
閉包就是作用域的特殊使用方式缰儿。
二、全局變量和局部變量散址。
1乖阵、全局變量
方式1
var a = 5;
注意:該句不能包含在function內(nèi)预麸,否則是局部變量瞪浸。
var n = 111;
function f1() {
console.log(n);
}
f1(); // 111
方式2
a = 5;
注意:即使該語(yǔ)句是在一個(gè)function內(nèi)师崎,當(dāng)該function被執(zhí)行后a變成了全局變量默终。
function f1() {
n = 999;
}
f1();
console.log(n)// 999
方式3
window.a;
window.a = 5;
注意:這種方式經(jīng)常被用到一個(gè)匿名函數(shù)執(zhí)行后將一些函數(shù)公開(kāi)到全局
window.jQuery = window.$ = jQuery;
2椅棺、局部變量
方式1
function f1(){
var n=999;
}
console.log(n) //error
在函數(shù)外部自然無(wú)法讀取函數(shù)內(nèi)的局部變量犁罩。
方式2
{
let q = 1 //局部變量
}
console.log(q)//error
三、外部讀取局部變量
正常情況下两疚,外部是無(wú)法讀取局部變量的床估;只有通過(guò)變通方法才能實(shí)現(xiàn)。
方法1
再定義一個(gè)函數(shù)
function f1() {
var n = 111;
function f2() {
console.log(n); //111
}
}
既然f2可以讀取f1中的局部變量诱渤,那么只要把f2作為返回值丐巫,就可以在f1的外部讀取它內(nèi)部的局部變量了。
function f1() {
var n = 111;
function f2() {
console.log(n); //111
}
return f2
}
var a = f1();
a()//111
方法2
運(yùn)用window做通訊勺美。
//在一個(gè)立即執(zhí)行函數(shù)訪問(wèn)另一個(gè)立即執(zhí)行函數(shù)中的值
! function () {
var a = 1 //局部變量
window.username = a //a賦值給window,window是全局變量
}()
! function () {
console.log(window.username) //通過(guò)window取得a的值
}()
在海洋中兩座孤島之間递胧,靠船來(lái)通訊(window)。
如圖:
方法3
在一個(gè)立即執(zhí)行函數(shù)訪問(wèn)另一個(gè)立即執(zhí)行函數(shù)中的值赡茸,只能讀缎脾。
! function () {
var user = {
name: 'lili',
age: 20
}
window.users = {
names: function () {
return user.name
},
ages: function () {
return user.age
}
}
//不能讓別的作用域改user,只能讀占卧。
}()
! function () {
window.users.names() // lili
window.users.ages() // 20
}()
四遗菠、閉包用途
一般情況下使用閉包是為了:
1联喘、可以讀取函數(shù)內(nèi)部的變量,如:方法1 方法2
2辙纬、暫存數(shù)據(jù)
function f1(){
var n=999;
nAdd=function(){n+=1}
function f2(){
console.log(n);
}
return f2;
}
var result=f1();
result(); // 999
nAdd();
result(); // 1000
在這段代碼中豁遭,result實(shí)際上就是閉包f2函數(shù)。它一共運(yùn)行了兩次贺拣,第一次的值是999蓖谢,第二次的值是1000。這證明了譬涡,函數(shù)f1中的局部變量n一直保存在內(nèi)存中蜈抓,并沒(méi)有在f1調(diào)用后被自動(dòng)清除。
這段代碼中另一個(gè)值得注意的地方昂儒,就是“nAdd=function(){n+=1}”這一行沟使,首先在nAdd前面沒(méi)有使用var關(guān)鍵字,因此nAdd是一個(gè)全局變量渊跋,而不是局部變量腊嗡。其次,nAdd的值是一個(gè)匿名函數(shù)(anonymous function)拾酝,而這個(gè)匿名函數(shù)本身也是一個(gè)閉包燕少,所以nAdd相當(dāng)于是一個(gè)setter,可以在函數(shù)外部對(duì)函數(shù)內(nèi)部的局部變量進(jìn)行操作
五蒿囤、總結(jié)
1客们、有一個(gè)地方需要注意,函數(shù)內(nèi)部聲明變量的時(shí)候材诽,一定要使用var命令底挫。如果不用的話,你實(shí)際上聲明了一個(gè)全局變量脸侥,如:方式2
2建邓、閉包會(huì)在父函數(shù)外部,改變父函數(shù)內(nèi)部變量的值睁枕。如:方法3
3官边、由于閉包會(huì)使得函數(shù)中的變量都被保存在內(nèi)存中,內(nèi)存消耗很大外遇,所以不能濫用閉包注簿。
參考:
MDN