函式
函式是一個物件,所以,它也可以擁有自己的屬性。
它可以被存放在變數、陣列中。
函式運算式-有括號和沒括號的差別
1 | function inner() { |
從console.log的結果a是直接印出整個inner函式內容,而b是印出inner回傳的內容’hello’。
那最後那一行,a()就可以執行inner函式,故會回傳內容’hello’。
要小心它們之間的不同喔~~~~
ES6箭頭函式
這種函式有以下的特性:
.this
變數的強制綁定
.簡短的撰寫方式
接下來,筆記一下箭頭函式可以簡寫的一些特性:
可以忽略return的特性
原本的函式
1 | const plus = function(numA, numB) { |
像上面這個範例,只有需要return計算的結果的話,除了箭頭函式的內容以外,我們還可以把return忽略。
所以,就會變成下面這樣:
1 | const plus = (numA, numB) => numA + numB; |
若箭頭函式中的括號中沒有參數是不行忽略的括號的
1 | const sayhello = () => console.log('hello'); |
若箭頭函式中的括號只有一個參數的話,可以忽略括號
1 | const sayhello(msg) => console.log(msg); |
arguments 物件
在函式被呼叫的時候,會產生arguments物件,而這個argument物件就會包含了我們所傳入的參數內容。
這個arguments物件是類似於物件的東西,既然是類似,所以,它就不會有陣列才擁有的一些方法,但是,利用迴圈來遍歷這個類陣列的arguments物件,
還是可以的喔。
所以,當我們不確定該函式會傳入多少個參數的時候,不管是少或多,我們都能透過arguments來得到這些傳入的參數。
1 | const plus = function(){ |
以上這個範例我們可以看到,就算在定義plus函數的時候,並沒有規定要傳入參數,但是,我們刻意傳入參數,最終,還是可以透過arguments來取得這些傳入的內容喔。
執行遞迴 - callee
我們可以利用arguments的一個屬性叫callee,它會回傳目前正在執行的函式。
如此,我們就可以透過它在該函式執行時,在其內部再利用callee再次呼叫正在執行的函式,形成遞迴的效果。
但這邊要特別注意,前面介紹過的ES6箭頭函式是不能呼叫arguments物件的喔。
箭頭函式使用其餘參數
雖然我們沒辦法在箭頭函式的情境下使用arguments物件,但是,我們可以使用其餘參數來達到一樣的效果。
那這邊其餘參數跟arguments物件比較不同的是,其餘參數是一個真正的陣列,所以,我們可以對它使用陣列才有的方法。
1 | const plus = (...argu) => { |
將以上例子改寫成直接使用陣列的方法
1 | const plus = (...argu) => argu.reduce((a, b) => a + b); |
CallBack Function
這種形式的函式的特性就是,當滿足某種條件時,此函式才會被被動的執行,我們就可以稱該函式為callback function。
那我們很常會在addEventListener的狀態下使用到CallBack Function。
1 | let el = document.querySelector('.btn'); |
像以上這個範例中在點擊了btn就會觸發addEventListener裡面的第二個參數,也就是那個匿名函式,啽這個匿名函式就是一個CallBack Function。
利用CallBack Function 控制函式執行的順序
我們可以透過將某個函式傳入另一個函式中,來達到先處理a函式後,才處理b函式。
1 | let funA = function(callback) { |
以上這個範例,我們把funB的呼叫包在funA裡面,呼叫,所以,不管何時執行A函式,都一定是在執行console.log('function A')
,之後,
才會去執行B函式。
CallBack Hell
如果我們依照上面這個方式來安排函式之間的執行順序,但是,當函式的量一多,呼叫來呼叫去的,你的程式碼會直接變成CallBack 修羅場。
也就是書中有提到的CallBack Hell,那這種現象可以利用Promise來解決這種問題囉。
立即函式
立即函式顧名思義就是當下就會被執行的函式。
1 | for(var i=0; i!=3; i++) { |
以上這個經典範例,我們會利用立即函式直接將當下的i變數,直接傳入該立即函式,並執行裡面的setTimeout函式。
同步 v.s 非同步
書中這邊講得蠻清楚的,所以,很值得紀錄一下~
非同步的概念
假設今天要做一道花枝炒飯。
今天這是一間大飯店,它有多位廚師,其中一位廚師處理花枝,另外一位廚師處理炒飯的部分,
所以,在這個過程中可能花枝先煮好,或者,炒飯先炒好,但沒關係,等到兩道菜都做好後,再一起裝盤出菜。
所以,非同步處理事件的流程,並不會其中一個步驟而被卡住,這個就是非同步的概念。
同步的概念
一樣要做花枝炒飯,
但這是一間小店,它只有一位廚師,所以,他得先處理完花枝後,再接著處理炒飯的部分。
所以,只能等到一項項目處理完之後,才能再接著處理下一個項目。
所以,同步的處理事件的概念是,先完成1之後,才能再依序處理2, 3, 4…。
所以,同步這個名詞乍看真的很像全部一起處理,但其實它是一步一步,按部就班的處理。
而非同步則是可以同時處理多件事情,不用互等。
不使用Promise就控制函式的操作順序
那如果我們希望在非同步的狀態下,想要先不用Promise的方法來達成控制函式的執行順序的話,書中有提供以下的寫法,我順便練習一下,
以上這個範例就可以看到,等到A, B, C這三個函式都執行完後,才執行D這個函式。
但是需要控制的函式一多的話,就會陷入Callback Hell的窘境,所以,我們就需要借助Promise的力量囉~