咱們都知道函數是被設計爲執行特定任務的代碼塊,會在某代碼調用它時被執行,得到返回值或者實現其餘功能。函數有函數名和參數,而函數參數是當調用函數接收的真實的值。html
今天要說的高階函數的英文爲Higher-order function
, 高階函數的高階是什麼意思呢?前端
至少知足下列一個條件的函數數組
- 接收一個或多個函數做爲輸入
- 輸出一個函數
怎麼理解這麼個東西呢?引言裏說過了,函數實際上都是指向某個變量。既然變量能夠是一個向函數,函數的參數能接收變量,那麼一個函數就能夠接收另外一個函數做爲參數,這種函數就稱之爲高階函數bash
//一個簡單的高階函數
function add(x,y,f){
return f(x)+f(y);
}
var x=add(-5,6,Math.abs); //-> 11
複製代碼
JS中設置了一些高階函數,好比Array.prototype.map
,Array.prototype.filter
和Array.prototype.reduce
,他們接收一個函數做爲參數,並應用這個函數到列表的每個元素。app
map()
方法建立一個新數組,其結果是該數組中的每一個元素都調用一個提供的函數後返回的結果,原始數組不會改變。函數
舉個栗子~咱們有個函數f(x)=x2,要把這個函數做用在一個數組[1, 2, 3, 4, 5, 6, 7, 8, 9]
上,就能夠用map實現:測試
fuction pow(x){
return x*x;
}
var arr=[1, 2, 3, 4, 5, 6, 7, 8, 9];
var result=arr.map(pow); //[1, 4, 9, 16, 25, 36, 49, 64, 81]
console.log(results);
複製代碼
值得注意的點:map()
傳入的參數是pow
,即一個函數對象自己。ui
雖然不用高階函數依靠循環也能實現上述功能,可是做爲高階函數能夠計算任意複雜的函數,也體現了高階函數的價值。spa
reduce()
方法對數組中的每一個元素執行一個提供的reducer
函數(升序執行),將其結果彙總爲單個返回值。prototype
Array
的reduce()
把一個函數做用在這個Array
的[x1, x2, x3...]
上,這個函數必須接收兩個參數,reduce()
把結果繼續和序列的下一個元素作累積計算,其效果就是:
[x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)
複製代碼
比方說對一個Array
求和,就能夠用reduce
實現:
var arr=[1,3,5,7,9];
arr.reduce(function(x,y){
return x+y;
}); //-> 25
複製代碼
filter()
方法建立一個新數組, 其包含經過提供函數實現的測試的全部元素,原始數組不會改變。
filter
也是一個經常使用的操做,它用於把Array
的某些元素過濾掉,而後返回剩下的元素。 和map()
相似,Array
的filter()
也接收一個函數。和map()
不一樣的是,filter()
把傳入的函數依次做用於每一個元素,而後根據返回值是true
仍是false
決定保留仍是丟棄該元素。
例如,在一個Array中,刪除偶數,只保留奇數:
var arr=[1,2,3,4,5,6,7,8];
var r=arr.filter(function(x){
return (x%2 !==0);
});
console.log(r); //=> [1,3,5,7]
複製代碼
把一個Array中的空字符刪除:
var arr = ['A', '', 'B', null, undefined, 'C', ' '];
var r = arr.filter(function (s) {
return s && s.trim(); // 注意:IE9如下的版本沒有trim()方法
});
r; // ['A', 'B', 'C']
複製代碼
因此!filter()
其實是一個篩選函數。
回調函數
filter()
接收的回調函數其實能夠有不少個參數。一般咱們僅使用第一個參數,表示Array
的某個元素。回調函數還能夠接收另外兩個參數,表示元素的位置和數組自己:
這裏利用filter
巧妙地實現了去重(我以爲很酷)
var arr = ['A', 'B', 'C'];
var r = arr.filter(function (element, index, self) {
console.log(element); // 依次打印'A', 'B', 'C'
console.log(index); // 依次打印0, 1, 2
console.log(self); // self就是變量arr
return true;
});
var r,arr=['apple', 'strawberry', 'banana', 'pear', 'apple', 'orange', 'orange', 'strawberry'];
r=arr.filter(function(element,index,self){
return self.indexOf(element)===index;
});
複製代碼
除了上述的幾個經常使用的高階函數,還有不少比較厲害的高階函數,包括sort()
,every()
,finf()
,findIndex()
,forEach()
等等,我會附在文章下面的參考中。
顧名思義,就是返回一個函數嘛,直接上例子:
咱們能夠用Object.prototype.toString.call
來獲取對應對象返回的字符串,來判斷類型
let isType = type => obj => {
return Object.prototype.toString.call( obj ) === '[object ' + type + ']';
}
isType('String')('123'); // true
isType('Array')([1, 2, 3]); // true
isType('Number')(123); // true
複製代碼
高階函數的功能很大程度上能夠用普通的函數實現,可是高階函數是代碼更加抽象容易理解,使功能更加簡潔,在函數複雜時能夠很便捷地實現須要的功能,是個很好很好的東西~
參考: 廖雪峯-高階函數 ; 木易楊前端進階-高階函數