一文瞭解JavaScript閉包函數

變量作用域

要理解JavaScript閉包,就要先理解JavaScript的變量作用域。

變量的作用域有兩種:全局的和局部的(全局變量和局部變量)

JavaScript中,在函數內部可以直接讀取到全局變量。

var n=10
function fn(){
	alert(n)
}
fn()      //10

而在函數外部無法讀取到函數內部的變量。

function fn(){
	var n=10;
}
fn()
alert(n)   //n is not defined    函數外部無法讀取到函數內部的n

註意:函數內部使用var聲明變量的時候,這個變量是局部變量,如果不使用var,那麼這個變量就是一個全局變量。

例如:

function fn(){
	n=10;
}
fn()
alert(n)   //10

另外,函數的參數也是局部性的,隻在函數內部起作用。

在正常情況下,我們是無法得到函數內部的局部變量的,隻有變通方法才可以——在函數內部再聲明一個函數。

function f1(){
	var n=10;
	function f2(){
		alert(n)
	}
}

f2函數可以得到f1函數內的所有局部變量,但是f1函數卻無法得到f2函數內部的局部變量——JavaScript語言特有的“鏈式作用域”結構。(即子對象會一級一級地向上尋找所有父對象的變量),所以,父對象的所有變量,對於子對象都是可見的。

f2函數可以獲取到父級函數f1的局部變量,那麼如果把f2()函數返回,在函數f1外部就可以訪問到f1()函數內部的變量瞭。

例如:

function f1(){
	var n=10;
	function f2(){
		alert(n)
	}
	return f2()
}
f1()           //頁面彈出10

例子中的f2()函數就是一個閉包函數。

閉包的概念

由於作用域原因,我們無法在函數外訪問函數裡面定義的變量,但有事我們又有這個需求,因此就出現瞭閉包的概念。

閉包是指有權訪問另一個函數作用域中的變量的函數。

在上面的例子中,內部函數f2就是一個閉包函數。

在本質上,閉包就是將函數內部和函數外部連接起來的橋梁。

閉包是一種保護私有變量的機制,在函數執行時形成私有的作用域,保護裡面的私有變量不受外界幹擾。

閉包的用途

(1)可以讀取父級作用域函數內部的變量;

(2)讓變量的值始終保存在內存中(讓局部變量變成全局變量),不被垃圾回收機制清除。

閉包的缺點

由於閉包會使函數中的變量都保存到內存中,垃圾回收機制不清理,內存消耗很大,所以不能濫用閉包,否則可能導致內存泄漏。

補充:

什麼是內存泄漏?

程序的運行都是需要內存的。隻要對內存提出要求,操作系統必須供給內存。
當應用程序中的一些代碼變量不再需要用到內存時,但是沒有被操作系統或者可用內存池回收,就說明它發生瞭內存泄漏。

即,當已經不再需要某塊內存時,這塊內存還存在著——內存泄漏

解決閉包引起的內存泄漏的問題:

在退出函數之前,將不使用的局部變量全部刪除。

例如:將當前變量的值設置為‘null’,當垃圾回收機制啟動時,會自動對這些值為‘null’的變量回收。

最後總結一下閉包的好處與壞處

好處

①保護函數內的變量安全 ,實現封裝,防止變量流入其他環境發生命名沖突

②在內存中維持一個變量,可以做緩存(但使用多瞭同時也是一項缺點,消耗內存)

③匿名自執行函數可以減少內存消耗

壞處

①其中一點上面已經有體現瞭,就是被引用的私有變量不能被銷毀,增大瞭內存消耗,造成內存泄漏,解決方法是可以在使用完變量後手動為它賦值為null;

②其次由於閉包涉及跨域訪問,所以會導致性能損失,我們可以通過把跨作用域變量存儲在局部變量中,然後直接訪問局部變量,來減輕對執行速度的影響

總結

到此這篇關於JavaScript閉包函數的文章就介紹到這瞭,更多相關JavaScript閉包函數內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: