您當前的位置:首頁 > 文化

JS前端閉包是什麼?私有變數可以用到閉包。

作者:由 小焱 發表于 文化時間:2022-03-07

JS前端閉包是什麼?私有變數可以用到閉包。

什麼是閉包?

百度百科定義:閉包就是能夠讀取其他函式內部變數的函式。建立閉包的通常方式,是在一個函式內部建立另一個函式

最常見的閉包結構如下

function

aaa

(){

var

name

=

“xxx”

return

function

bbb

(){

alert

name

);

}

}

如上程式碼,bbb函式內可以訪問aaa函式作用域內的變數

閉包解決了什麼問題?

1。 可以讀取函式內部的變數;

2。 讓這些變數的值始終保持在記憶體中。不會在函式呼叫後被清除;

閉包的定義及其優缺點

閉包

是指有權訪問另一個函式作用域中的變數的函式,建立閉包的最常見的方式就是在一個函式內建立另一個函式,透過另一個函式訪問這個函式的區域性變數

閉包的缺點就是常駐記憶體,會增大記憶體使用量,使用不當很容易造成記憶體洩露。

閉包是

javascript

語言的一大特點,主要應用閉包場合主要是為了:設計私有的方法和變數。

一般函式執行完畢後,區域性活動物件就被銷燬,記憶體中僅僅儲存全域性作用域。但閉包的情況不同!

avascript

的垃圾回收原理

(1)、在

javascript

中,如果一個物件不再被引用,那麼這個物件就會被

GC

回收;

(2)、如果兩個物件互相引用,而不再被第

3

者所引用,那麼這兩個互相引用的物件也會被回收。

使用閉包的好處

那麼使用閉包有什麼好處呢?使用閉包的好處是:

1。希望一個變數長期駐紮在記憶體中

2。避免全域性變數的汙染

3。私有成員的存在

全域性變數

函式可以訪問由函式內部定義的變數,如:

function

myFunction

()

{

var

a

=

4

return

a

*

a

}

函式也可以訪問函式外部定義的變數,如:

var

a

=

4

function

myFunction

()

{

return

a

*

a

}

計數器困境

設想下如果你想統計一些數值,且該計數器在所有函式中都是可用的。

你可以使用全域性變數,函式設定計數器遞增:

var

counter

=

0

function

add

()

{

return

counter

+=

1

}

add

();

add

();

add

();

// 計數器現在為 3

但問題來了,頁面上的任何指令碼都能改變計數器,即便沒有呼叫 add() 函式。

如果我在函式內宣告計數器,如果沒有呼叫函式將無法修改計數器的值:

function

add

()

{

var

counter

=

0

return

counter

+=

1

}

add

();

add

();

add

();

// 本意是想輸出 3, 但事與願違,輸出的都是 1 !

JavaScript 巢狀函式

所有函式都有權訪問全域性作用域。

事實上,在 JavaScript 中,所有函式都有權訪問它們“上面”的作用域。

JavaScript 支援巢狀函式。巢狀函式可以訪問其上的作用域。

在本例中,內部函式 plus() 可以訪問父函式中的 counter 計數器變數:

function

add

()

{

var

counter

=

0

function

plus

()

{

counter

+=

1

;}

plus

();

return

counter

}

這樣即可解決計數器困境,如果我們能夠從外面訪問 plus() 函式。

我們還需要找到只執行一次 counter = 0 的方法。

我們需要閉包(closure)。

JavaScript 閉包

還記得函式自我呼叫嗎?該函式會做什麼?

var

add

=

function

()

{

var

counter

=

0

return

function

()

{

return

counter

+=

1

;}

})();

add

();

add

();

add

();

// 計數器為 3

例子解釋

變數 add 的賦值是自呼叫函式的返回值。

這個自呼叫函式只執行一次。它設定計數器為零(0),並返回函式表示式。

這樣 add 成為了函式。最“精彩的”部分是它能夠訪問父作用域中的計數器。

這被稱為 JavaScript

閉包

。它使函式擁有“

私有

”變數成為可能。

計數器被這個匿名函式的作用域保護,並且只能使用 add 函式來修改。

閉包指的是有權訪問父作用域的函式,即使在父函式關閉之後。

技巧1: 用閉包解決遞迴呼叫問題

function

factorial

num

{

if

num

<=

1

{

return

1

}

else

{

return

num

*

factorial

num

-

1

}

}

var

anotherFactorial

=

factorial

factorial

=

null

anotherFactorial

4

// 報錯 ,因為最好是return num* arguments。callee(num-1),arguments。callee指向當前執行函式,但是在嚴格模式下不能使用該屬性也會報錯,所以藉助閉包來實現

// 使用閉包實現遞迴

function

newFactorial

=

function

f

num

){

if

num

<

1

{

return

1

}

else

{

return

num

*

f

num

-

1

}

})

//這樣就沒有問題了,實際上起作用的是閉包函式f,而不是外面的函式newFactorial

技巧2:用閉包模仿塊級作用域

es6沒出來之前,用var定義變數存在變數提升問題:

for

var

i

=

0

i

<

10

i

++

){

console

info

i

}

alert

i

// 變數提升,彈出10

//為了避免i的提升可以這樣做

function

()

{

for

var

i

=

0

i

<

10

i

++

){

console

info

i

}

})()

alert

i

// underfined 因為i隨著函式的退出,執行環境銷燬,變量回收

標簽: 函式  閉包  add  計數器  作用域