詳解JavaScript閉包問題
閉包是純函數(shù)式編程語(yǔ)言的傳統(tǒng)特性之一。通過將閉包視為核心語(yǔ)言構(gòu)件的組成部分,JavaScript語(yǔ)言展示了其與函數(shù)式編程語(yǔ)言的緊密聯(lián)系。由于能夠簡(jiǎn)化復(fù)雜的操作,閉包在主流JavaScript庫(kù)以及高水平產(chǎn)品代碼中日益流行起來。
一、變量的作用域
在介紹閉包之前,我們先理解JavaScript的變量作用域。變量的作用域分為兩種:全局變量和局部變量。
1、全局變量
var n = 999; //全局變量
function f1() {
a = 100; //在這里a也是全局變量
alert(n);
}
console.log(a); //100
在這里,函數(shù)內(nèi)外部可以直接取到變量的值——全局變量
2、局部變量
//局部變量
function f2() {
var b = 22;
}
console.log(b); //報(bào)錯(cuò)
在這里,函數(shù)外部無法直接取到函數(shù)內(nèi)部定義的值——局部變量
講到這里,當(dāng)我們想要從外部取到局部變量的值,這時(shí)候該怎么辦呢?
請(qǐng)接著往下看:
二、如何從外部獲取局部變量
接下來我們看一個(gè)例子:
var outer = 'Outer'; // 全局變量
var copy;
function outerFn(){ // 全局函數(shù)
var inner = 'Inner'; // 該變量只有函數(shù)作用域,無法從外部訪問
function innerFn(){ // outerFn()中的innerFn()
// 全局上下文和外圍上下文都可以在這里使用,
// 因此可以訪問到outer和inner
console.log(outer);
console.log(inner);
}
copy=innerFn; // 保存innerFn()的引用
// 因?yàn)閏opy是在全局上下文中聲明的,所以在外部可以使用
}
outerFn();
copy(); // 不能直接調(diào)用innerFn(),但是可以通過在全局作用域中聲明的變量來調(diào)用
來分析一下上面的例子。在innerFn()中可以訪問變量outer,因?yàn)樗幱谌稚舷挛闹小?/span>
在執(zhí)行完outerFn()之后,執(zhí)行了innerFn(),這是通過將該函數(shù)的引用復(fù)制到一個(gè)全局變量
copy中來實(shí)現(xiàn)的。在利用變量copy調(diào)用函數(shù)innerFn()執(zhí)行時(shí),此刻已經(jīng)不在outerFn()的作
用域中了。因此下面的代碼不是應(yīng)該失敗嗎?
console.log(inner);
變量inner的值應(yīng)該是undefined吧?可是,上面代碼片段的輸出卻是:
“Outer”
“Inner”
這就是JavaScript的鏈?zhǔn)阶饔糜蚪Y(jié)構(gòu),子對(duì)象會(huì)一級(jí)一級(jí)的向上尋找所有父對(duì)象的變量。所以父對(duì)象的所有變量對(duì)子對(duì)象都是可見的,反之則不成立。
這樣我們就可以獲取到函數(shù)內(nèi)部的局部變量了。
三、閉包的概念
上面代碼塊中的copy()函數(shù)就是閉包。在我的理解,閉包就是能夠讀取到函數(shù)內(nèi)部變量的函數(shù)。
而在JavaScript中,可以通過函數(shù)內(nèi)部的子函數(shù)獲取到局部變量,因此可以把閉包理解為定義在函數(shù)內(nèi)部的函數(shù)。
可以把它理解為一個(gè)將函數(shù)內(nèi)部和外部連接起來的橋梁。
四、閉包的作用
在我看來,閉包的作用主要體現(xiàn)在兩個(gè)方面:
1、可以讀取函數(shù)內(nèi)部的變量
這個(gè)作用在上個(gè)代碼塊已經(jīng)表現(xiàn)得很清楚。
2、可以將局部變量的值一直保存在內(nèi)存中
總所周知,局部變量只有當(dāng)使用的時(shí)候才會(huì)在內(nèi)存中開辟出暫時(shí)的存儲(chǔ)空間,在函數(shù)運(yùn)行結(jié)束后會(huì)自動(dòng)釋放空間。而閉包的出現(xiàn)可以使得局部變量可以像全局變量一樣一致存儲(chǔ)在內(nèi)存中。
function c1() {
var z = 9999;
nAdd = function() {
z += 1;
}
function c2() {
console.log(z);
}
return c2;
}
var result = c1();
result(); //9999
nAdd();
result(); //10000
在上述代碼中,先執(zhí)行一次c1(),此時(shí)z=9999;再執(zhí)行一次nAdd(),使z+1;在執(zhí)行一次c1()輸出此時(shí)z的值,z=10000。說明z的值一直存儲(chǔ)在內(nèi)存中,并沒有在第一次調(diào)用c1()后背自動(dòng)消除。
此時(shí)就要注意,閉包的使用會(huì)消耗很大的內(nèi)存,不要濫用閉包。在退出函數(shù)之前,將不使用的局部變量全部刪除。
到此這篇關(guān)于詳解JavaScript閉包問題的文章就介紹到這了,更多相關(guān)JavaScript閉包問題內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Javascript獲取窗口(容器)的大小及位置參數(shù)列舉及簡(jiǎn)要說明
Javascript獲取窗口(容器)的大小及位置一系列的東西比較多,容易混淆,在這里列舉及簡(jiǎn)要說明下,需要的朋友可以參考下2012-12-12
javascript模塊化是什么及其優(yōu)缺點(diǎn)介紹
模塊化是一種將系統(tǒng)分離成獨(dú)立功能部分的方法,可將系統(tǒng)分割成獨(dú)立的功能部分,嚴(yán)格定義模塊接口、模塊間具有透明性2013-09-09
JavaScript之?dāng)?shù)組(Array)詳解
這篇文章主要介紹了JavaScript之?dāng)?shù)組(Array)詳解,本文詳細(xì)講解了JavaScript數(shù)組的創(chuàng)建、檢測(cè)數(shù)組、轉(zhuǎn)化方法、棧方法、隊(duì)列方法、重排序方法、操作方法、位置方法等內(nèi)容,需要的朋友可以參考下2015-04-04
javaScript parseInt字符轉(zhuǎn)化為數(shù)字函數(shù)使用小結(jié)
前幾天做網(wǎng)站的時(shí)候需要講數(shù)據(jù)庫(kù)中的時(shí)間讀取到變量中進(jìn)行使用,用到parseInt函數(shù),講字符轉(zhuǎn)化為數(shù)字。2009-11-11
JavaScript 內(nèi)置對(duì)象屬性及方法集合
JavaScript內(nèi)置對(duì)象屬性及方法大全,學(xué)習(xí)js的朋友可以收藏下, 方便以后的學(xué)習(xí)。2010-07-07
JavaScript cookie詳解及簡(jiǎn)單實(shí)例應(yīng)用
這篇文章主要介紹了JavaScript cookie詳解及簡(jiǎn)單實(shí)例應(yīng)用的相關(guān)資料,這里對(duì)js cookie 的介紹及基本屬性和簡(jiǎn)單應(yīng)用做了詳解,需要的朋友可以參考下2016-12-12
JavaScript中__proto__與prototype的關(guān)系深入理解
本文將討論下對(duì)象的內(nèi)部原型(__proto__)和構(gòu)造器的原型(prototype)的關(guān)系,需要了解更多的朋友可以參考下2012-12-12
深入解析JavaScript中的立即執(zhí)行函數(shù)
立即執(zhí)行函數(shù)模式在JavaScript中可以讓你的函數(shù)在定義后立即被執(zhí)行,下面我們就來深入解析JavaScript中的立即執(zhí)行函數(shù),需要的朋友可以參考下2016-05-05

