與Lisp谅猾,Haskell不同自沧,JavaScript并非函數(shù)式編程語言,但在JS之中可以像操控對(duì)象一樣操控函數(shù)廊酣,換句話說锉罐,可以在JS中應(yīng)用函數(shù)式編程技術(shù)帆竹。
什么是函數(shù)式編程?
?函數(shù)式編程通過使用函數(shù)來將值轉(zhuǎn)換成抽象單元脓规,接著用于構(gòu)建軟件系統(tǒng)栽连。
舉個(gè)很普通且低級(jí)的例子:假設(shè)有一個(gè)數(shù)組,數(shù)組元素都是數(shù)字侨舆,我們想要計(jì)算它的平均值和標(biāo)準(zhǔn)差秒紧,如果使用非函數(shù)式編程那么就是這個(gè)樣子:
var data = [1,2,3,4,5];
var total = 0;
for(var i = 0; i < data.length; i++)
total += data[i];
var mean = total / data.length; //平均數(shù)為3
total = 0;
for(var i = 0; i < data.length; i++) {
var deviation = data[i] - mean;
total += deviation * deviation;
}
var stddev = Math.sqrt(total / (data.length-1)); //標(biāo)準(zhǔn)差為2
采用函數(shù)式編程那么就是這個(gè)樣子(這里會(huì)用到數(shù)組方法map()和reduce(),ES3未包含這兩種方法,所以下面會(huì)先進(jìn)行判斷,如果有map()和reduce()就直接使用挨下,否則就自行定義):
var map = Array.prototype.map?function(a, f) { return a.map(f); }
:function(a, f) {
var results = [];
for(var i = 0,len = a.length; i < len; i++) {
if (i in a) results[i] = f.call(null,a[i],i,a);
}
return results;
};
var reduce = Array.prototype.reduce?function(a,f,initial) {
if(arguments.length > 2)
return a.reduce(f, initial);
else
return a.reduce(f);
}
: function(a,f,initial) {
var i = 0, len = a.length,accmulator;
if(arguments, length > 2)
accmulator = initial;
else{
if(len == 0)
throw TypeError();
while( i < len){
if(i in a){
accumulator = a[i++];
break;
}
else
i++;
}
if(i == len) throw TypeError();
}
while( i < len) {
if ( i in a)
accumulator = f.call(undefined, accumulator,a[i],i,a);
i++;
}
return accumulator;
});
//下面的代碼塊就是函數(shù)式編程
var sum = function(x,y) { return x+y; };
var square = function(x) { return x*x;};
var data = [1,2,3,4,5];
var mean = data.reduce(sum) / data.length;
var deviations = data.map(function(x) { return x-mean;});
var stddev = Math.sqrt(deviations.map(square).reduce(sum) / (data.length - 1));
用嚴(yán)格的函數(shù)式編程的方法來解決問題熔恢,會(huì)將一個(gè)問題分成幾部分(函數(shù))來解決。如下圖:
函數(shù)式編程通過“組合”其他函數(shù)的方式來構(gòu)建更大的函數(shù)臭笆,以實(shí)現(xiàn)更抽象的行為如下圖:
最終叙淌,一種將函數(shù)的部件組成一個(gè)完整的系統(tǒng)的方法是取一個(gè)值秤掌,逐漸的將它“改變”——通過一個(gè)原始的或組合的函數(shù)——成為另外一個(gè)值。