今天來看函數程式設計的兩節影片
(udemy這系列影片稱呼Function為函數,但我個人比較習慣稱呼函式)
函數程式設計課程不可能在一兩節影片就講完,作者解釋他只是希望在這系列課程引入這個概念,以簡短影片讓人先體會它的威力。
先來看看以下程式碼
var arr1 = [1, 2, 3];
var arr2 = [];
現在有陣列arr1、arr2,我們想要複製arr1陣列的內容給arr2,並讓arr2陣列的值變arr1的2倍。
一般接續內容可能這樣寫:
for(var i=0; i < arr1.length; i++){
arr2.push(arr1[i] * 2);
}
console.log(arr2);
結果是
因為JS具有一級函式
的特性,我們可以將程式步驟拆成一個個函式,透過函式來讓程式碼更有結構性。
改成這樣
var arr1 = [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 arr2 = mapForEach(arr1, function(item){
return item * 2;
});
console.log(arr2);
說明
將建立arr1以外的新陣列程式碼,改在mapForEach函式裏頭處理,然後用變數arr2指向呼叫mapForEach函式後的的回傳值。
呼叫mapForEach函式時帶入兩個參數,一是參考對象陣列,二是匿名函式,告訴mapForEach函式要處理什麼,這裡告訴mapForEach要將陣列參數乘與二並回傳。
結果是
這種做法比原本的方式複雜,優點在哪?
若我們突然需要比對陣列的值(例如是否有值大於2),就可以接續程式碼很快地新增內容
var arr3 = mapForEach(arr1, function(item){
return item > 2;
});
console.log(arr3);
也就是說,利用獨立出mapForEach函式這種寫法,我們可以更方便的對陣列做各種運算。
我們也可以用bind()來修改比較是否超過2這個函式,這次將函式修改得更具彈性。
var checkPastLimit = function(limiter, item){
return item > limiter;
}
建立變數指向checkPastLimit指向一個匿名函式,檢查傳入的item參數是否有超過傳入limiter參數。
接著
var arr4 = mapForEach(arr1, checkPastLimit.bind(this, 2));
console.log(arr4);
建立變數arr4並指向呼叫mapForEach後的回傳值,這裡一樣帶入arr1當參數,另一個參數帶入checkPastLimit,這裡用bind並不是要修改this,而是為了用bind
的特性預設參數,來達成function currying的目的,關於bind
可以看昨天的筆記。
結果是
那有沒有更簡潔的方法,有!
var checkPastLimitSimplified = function(limiter){
return function(limiter, item){
return item > limiter;
}.bind(this, limiter);
};
var arr5 = mapForEach(arr1, checkPastLimitSimplified(2));
console.log(arr5);
說明
建立變數checkPastLimitSimplified指向一個匿名函式,這個函式可以帶入參數limiter,若是執行它會回傳這個匿名函式
function(limiter, item){
return item > limiter;
}.bind(this, limiter);
這個被回傳的匿名函式,可以再帶入另一個參數limiter和item,然後回傳item參數是否大於limiter參數的布林值,我們用bind來預設一個參數limiter。
現在建立變數arr5,並指向呼叫mapForEach函式的回傳值,帶入arr1陣列與呼叫checkPastLimitSimplified(2)
的回傳值。
結果是
基本上就是利用閉包特性,return
再return
,但太簡潔的話,易讀性就不一定好了,這裡只是做為一個範例。
到這邊只用了幾行程式碼,就能快速創建不一樣的陣列,而且沒有功能重複的程式碼,
作者認為函數程式設計,一開始很難,但只要習慣分割程式到函式,讓函式互傳這種寫法,不僅程式碼簡潔,開發時速度也會快很多。
接下來的影片,作者提到了兩個函式庫:
他們都用到了函數程式設計的概念,並且語法簡潔、速度快,影片中很推崇。
作者推薦除了使用外,也可以下載js原始碼(開發者版本)來研究好的程式碼是怎麼撰寫、思考的。
接著的範例需要下載underscore.js才能繼續,在網頁引入underscore.js函式庫後,繼續程式碼的內容。
來看看以下程式碼
var arr6 = _.map(arr1, function(item){
return item * 3;
});
console.log(arr6);
_.map()
是underscore函式庫定義的函式,功能類似今天筆記的mapForEach函式
第一個參數一樣帶入arr1,結果是
再看看以下程式碼
var arr7 = _.filter([2,3,4,5,6,7], function(item){
return item % 2 === 0;
});
console.log(arr7);
_.filter
這個函式可以幫我們篩選陣列的值,帶入陣列[2,3,4,5,6,7]
作為filter函式第一個參數,然後第二個參數函式,內容是回傳第一個參數[2,3,4,5,6,7]
個別能夠被2整除的值。
結果是
小結
今天影片這樣看下來,使用函數程式設計的優點有
今天的筆記內容可以參照Udemy課程:JavaScript 全攻略:克服JS的奇怪部分4-51、4-51
抱歉來廣告一下。一般來說 JavaScript (或其它語言的) function 的確會翻譯成函式,但 functional programming 還是會叫做「函數式程式設計」。因為這兩個字的意義是不一樣的。詳情可以看我的這篇文章:https://ithelp.ithome.com.tw/articles/10192916 (雖然是不同的語言啦。) XD
原來如此
我還以為只是單純譯名不一樣哈哈!