輕鬆介紹閉包的主題,這是理解 JavaScript 函數如何運作的關鍵。

如果你曾經在 JavaScript 中寫過函數,你已經使用過閉包了。

這是一個需要理解的重要主題,會對你能做的事情產生影響。

當一個函數被執行時,它是在定義時的作用域中運行,而不是在執行時的狀態中運行。

作用域基本上是一組可見的變數。

一個函數記住了它的詞法作用域,它能夠訪問在父範圍中定義的變數。

簡而言之,一個函數能夠訪問一個完整的變數集合。

讓我馬上舉個例子來澄清這點。

const bark = dog => {
 const say = `${dog} barked!`
 ;(() => console.log(say))()
}

bark(`Roger`)

這將按預期將 Roger barked! 輸出到控制台。

如果你想返回這個動作呢:

const prepareBark = dog => {
 const say = `${dog} barked!`
 return () => console.log(say)
}

const bark = prepareBark(`Roger`)

bark()

這段代碼也會在控制台上輸出 Roger barked!

讓我們舉一個最後的例子,它使用 prepareBark 預先設定兩隻不同的狗:

const prepareBark = dog => {
 const say = `${dog} barked!`
 return () => {
 console.log(say)
 }
}

const rogerBark = prepareBark(`Roger`)
const sydBark = prepareBark(`Syd`)

rogerBark()
sydBark()

這段代碼將輸出:

Roger barked!
Syd barked!

正如你所看到的,變量 say狀態與從 prepareBark() 返回的函數相關聯。

同時請注意,我們在第二次調用 prepareBark() 時重新定義了一個新的 say 變量,但這並不會影響第一個 prepareBark() 作用域的狀態。

這就是閉包的工作方式:從 prepareBark() 返回的函數保留了原始狀態。