[JavaScriptWeird]No.39 函式程式設計

前言

討論完一級函式與 JavaScript 其他特色後,我們已經可以使用這些概念進行 JavaScript 中的函式程式設計 (Functional Programming),這很有趣也非常強大,但一開始不好掌握,需要多多練習。

函式程式設計 (Functional Programming)

JavaScript 乍聽之下好像跟 Java 有關、或是看起來有點像 C++、C#,但其實 JavaScript 與函式程式語言較相關,像是 Lisp、Scheme、ML,這些提到的語言都有一級函式的概念。

來點例子

1
2
3
4
5
6
7
var originArr = [1, 2, 3];  
console.log(originArr);
var outputArr = []; // [1,2,3]
for(var i = 0; i < originArr.length; i++) {
outputArr.push(originArr[i]*2);
}
console.log(outputArr); // [2,4,6]

這段程式很簡單,就只是把陣列的內容乘以 2 放到另一個陣列而已,這麼寫其實不算是有錯誤,還可以處理得更好。

這段程式,可以想成把某陣列的內容透過迴圈遍歷,並傳入某函式處理後,得到新的陣列。

因此可以整理出可能需要做的事情:

  • 需要一個可以傳入兩個參數的函式
    • 參數 - 某陣列以及「想如何處理」的函式
  • 需要迴圈跑完傳入陣列的所有內容
  • 函式最後需要回傳新陣列
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    var originArr = [1, 2, 3];  
    function mapForEach(arr, fn) {
    var newArr = [];
    for(var i = 0; i < arr.length; i++) {
    newArr.push(
    fn(arr[i])
    )
    }
    return newArr;
    }

    var outputArr = mapForEach(originArr, function(item){
    return item * 2;
    });
    console.log(outputArr);

透過這樣子的撰寫,可以做到同樣的事情,更棒的是可以更彈性的調整傳入的陣列輸出的結果,像是:

1
2
3
4
var outputArr2 = mapForEach(originArr, function(item){  
return item > 2;
});
console.log(outputArr2); // [false, false, true]

不必重新撰寫整個比大小的程式,只需要微調傳入的函式。

進階應用 - 結合 bind()

承接上面的例子,有時候可能需要傳入不只一個參數,假使我們傳入的函式需要用到更多參數,而不是上面的例子只有一個參數時該怎麼辦呢?

1
2
3
4
5
6
7
// 進階 - 利用先前的觀念將需要兩個參數的函式變成一個參數  
var checkPastLimit = function(limiter , item){
// 檢查傳入的 item 是否大於 limiter
return item > limiter;
}
var outputArr3 = mapForEach(originArr, checkPastLimit.bind(this,2))
console.log(outputArr3); // [false, false, true]

可以使用上一篇提到的 bind() 方法,將第一個參數設定固定預設值,就搞定囉,在這邊因為不會使用到 this 所以不重要。

另外同樣的做法,也可以這麼寫:

1
2
3
4
5
6
7
var checkPastLimitEasyUse = function(limiter) {  
return function(limiter , item){
return item > limiter;
}.bind(this,limiter);
}
var outputArr4 = mapForEach(originArr, checkPastLimitEasyUse(3));
console.log(outputArr4); // [false, false, false]

如果不想要每次都使用 bind() 方法,可以再用一個函式把原本的函式包覆並傳原本函式的內容,這樣就可以僅傳入一個參數使用囉。

後記

要把程式寫成具有函式程式設計概念是需要透過很大量練習的,期許自己能透過大量的練習,早日熟練這一塊。

現在的我還不能自在的使出這一招,寫出的程式碼大多類似像這篇文章的第一個範例,需要透過事後的整理才會變成第二個範例這樣,這也是我往後進行實作時可以練習的一個重點。

0%