天天看點

JavaScript學習之旅-10(原創)

上一篇文章

中,主要學習了JavaScript了map、reduce、filter、Sort等關鍵字的使用。這一篇文章我們主要學習JavaScript中的閉包,箭頭函數

閉包:

在說到閉包以前,我們先複習下JavaScript中的變量作用域。JavaScript中變量的作用域無非就是兩種:全局變量和局部變量。需要注意的是,函數内部可以直接讀取全局變量;但是在函數外部無法直接讀取函數内的局部變量。

舉個例子:

JavaScript學習之旅-10(原創)

其中:data是我們定義的全局變量,在test函數中,我們可以直接使用。是以彈窗也彈出了資料

但是,如果我們在函數裡面定義變量,然後直接通過外部引用,就會報錯,如下圖,異常資訊顯示第六行錯誤,那麼實際上是data 沒有定義,導緻的錯誤。因為data定義是在test函數裡面局部變量,外部直接使用局部變量就會報錯

JavaScript學習之旅-10(原創)

需要注意!!!函數内部聲明變量的時候,一定要使用var。如果不用的話,你實際上聲明了一個全局變量!如下圖:

JavaScript學習之旅-10(原創)

沒有使用var變量

那麼,正常情況下,如何從外部去擷取函數内部定義的變量? 閉包 可以幫助我們有效解決這個問題:

有權通路另一個函數作用域内變量的函數都是閉包。簡單點了解就是,我們在定義function的時候,希望從外部通路函數内部的變量,但是一般情況下是通路不了,

這時候我們就會在這個函數内部繼續定義一個子函數,因為子函數可以通路外部函數的變量。是以我們就可以将子函數作為結果傳回

,達到外部通路函數内部變量的效果。

JavaScript學習之旅-10(原創)

閉包 - 1

在上面的代碼中,函數 useClosePackage() 就被包括在函數 test()内部,這時 test()内部的所有局部變量,對 useClosePackage()都是可見的。

但是反過來就不行,内部的局部變量,對 test()就是不可見的。這就是Javascript語言特有的"鍊式作用域"結構,子對象會一級一級地向上尋找所有父對象的變量。是以,父對象的所有變量,對子對象都是可見的,反之則不成立。

既然 useClosePackage()可以讀取 test() 中的局部變量,那麼隻要把 useClosePackage()作為傳回值,我們不就可以在 test() 外部讀取它的内部變量了嗎!

下面就是一個簡單閉包的例子:

JavaScript學習之旅-10(原創)

當然,還可以這樣寫:

JavaScript學習之旅-10(原創)

閉包 - 2

另外,關于閉包有一個需要注意的是:

JavaScript學習之旅-10(原創)

閉包需要注意的事項

這段代碼的大概意思是:每次循環,都建立了一個新的函數,然後,把建立的3個函數都添加到一個Array中傳回了。(push() 方法就是向數組的末尾添加一個或多個元素,并傳回新的長度。)

你可能認為調用f1(),f2()和f3()結果應該是1,4,9,但實際結果是:卻是3個16,那麼這種原因是什麼導緻的?

原因就在于傳回的函數引用了變量 i,但它并非立刻執行。等到3個函數都傳回時,它們所引用的變量 i 已經變成了4,是以最終結果為(4 * 4 = 16)。

傳回閉包時牢記的一點就是:傳回函數不要引用任何循環變量,或者後續會發生變化的變量。

那麼,這種問題該如何解決?

解決辦法就是再建立一個函數,用該函數的參數綁定循環變量目前的值,無論該循環變量後續如何更改,已綁定到函數參數的值不變,這樣就可以有效解決上面的問題

代碼如下:

JavaScript學習之旅-10(原創)

也就是繼續套一層,就可以解決上述問題

還有一點需要注意的是,由于閉包會使得函數中的變量都被儲存在記憶體中,記憶體消耗很大,是以不能濫用閉包,否則會造成網頁的性能問題,在IE中可能導緻記憶體洩露。這種問題的解決方法是,在退出函數之前,将不使用的局部變量全部删除。

箭頭函數:

在說箭頭函數之前,我們先寫一個簡單的函數,這個函數主要是用來做加法算術的

JavaScript學習之旅-10(原創)

普通函數

但是在ES6标準之後,引入了箭頭函數這一個新概念,這個箭頭函數是幫助我們文法簡潔的一種形式,上面這個加法函數如果使用了箭頭函數的話,就可以寫成這樣:

JavaScript學習之旅-10(原創)

箭頭函數

那麼,我們首先理清箭頭函數的基本寫法格式以及原來寫法格式的對比:

1:沒有參數的兩種寫法對比

JavaScript學習之旅-10(原創)

沒有參數的寫法對比

2:有一個參數的兩種寫法對比

JavaScript學習之旅-10(原創)

有一個參數的寫法對比

3:有兩個參數的兩種寫法對比

JavaScript學習之旅-10(原創)

有兩個參數的寫法對比

4:函數體多條語句判斷的兩種寫法對比(注意:箭頭函數在這裡需要用到大括号)

JavaScript學習之旅-10(原創)

函數體多條語句判斷寫法對比

5:對象的寫法對比

JavaScript學習之旅-10(原創)

對象的原始寫法

JavaScript學習之旅-10(原創)

箭頭函數下對象的寫法

需要注意的是:因為對象是用花括号括起來的,是以在箭頭函數裡面,我們用小括号先在外面套一層,這樣才可以使用。

JavaScript學習之旅-8

這篇文章中,我們學習了this關鍵字,我們知道JavaScript中this關鍵字如果使用不當,會有指針指向問題,然後關于這個問題,我們可以額外使用一個變量去記錄this或者使用apply關鍵字去解決,那麼,現在由于箭頭函數的出現,又出現了一種新的解決辦法。

先回顧下this關鍵字的問題代碼

JavaScript學習之旅-10(原創)

this指向問題

這個問題在上面的連結有具體說明,那麼現在通過箭頭函數就可以有效規避上述問題:

如圖,隻是将擷取年齡的函數使用了箭頭函數去操作,即可擷取到我想要的結果:

JavaScript學習之旅-10(原創)

總結:

1、箭頭函數沒有自己的this。箭頭函數會捕獲其所在上下文的 this 值,作為自己的 this 值。 

2、箭頭函數 this 不可變。call()、apply()、bind()、這些方法也 無法改變 箭頭函數 this 的指向。

3、箭頭函數 不能用 new 關鍵字來執行個體化對象,不然會報錯。 

4、箭頭函數沒有arguments對象。

本篇文章主要學習的是關于閉包、箭頭函數的使用。本章的基本内容就結束了。

未完待續。。。

如果這篇文章對你有幫助,希望各位看官留下寶貴的star,謝謝。

Ps:著作權歸作者所有,轉載請注明作者, 商業轉載請聯系作者獲得授權,非商業轉載請注明出處(開頭或結尾請添加轉載出處,添加原文url位址),文章請勿濫用,也希望大家尊重筆者的勞動成果。

繼續閱讀