淺談JS高階函數

引入

咱們都知道函數是被設計爲執行特定任務的代碼塊,會在某代碼調用它時被執行,得到返回值或者實現其餘功能。函數有函數名和參數,而函數參數是當調用函數接收的真實的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.mapArray.prototype.filterArray.prototype.reduce,他們接收一個函數做爲參數,並應用這個函數到列表的每個元素。app

Array.prototype.map

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

Array.prototype.reduce

reduce()方法對數組中的每一個元素執行一個提供的reducer函數(升序執行),將其結果彙總爲單個返回值。prototype

Arrayreduce()把一個函數做用在這個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
複製代碼

Array.prototype.filter

filter() 方法建立一個新數組, 其包含經過提供函數實現的測試的全部元素,原始數組不會改變

filter也是一個經常使用的操做,它用於把Array的某些元素過濾掉,而後返回剩下的元素。 和map()相似,Arrayfilter()也接收一個函數。和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

複製代碼

總結

高階函數的功能很大程度上能夠用普通的函數實現,可是高階函數是代碼更加抽象容易理解,使功能更加簡潔,在函數複雜時能夠很便捷地實現須要的功能,是個很好很好的東西~


參考: 廖雪峯-高階函數 ; 木易楊前端進階-高階函數

相關文章
相關標籤/搜索