淺談JS高階函數


引入

我們都知道函數是被設計為執行特定任務的代碼塊,會在某代碼調用它時被執行,獲得返回值或者實現其他功能。函數有函數名和參數,而函數參數是當調用函數接收的真實的值。

今天要說的高階函數的英文為Higher-order function, 高階函數的高階是什么意思呢?

定義

至少滿足下列一個條件的函數

  • 接收一個或多個函數作為輸入
  • 輸出一個函數

怎么理解這么個東西呢?引言里說過了,函數實際上都是指向某個變量。既然變量可以是一個向函數,函數的參數能接收變量,那么一個函數就可以接收另一個函數作為參數,這種函數就稱之為高階函數

//一個簡單的高階函數
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,他們接收一個函數作為參數,並應用這個函數到列表的每一個元素。

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,即一個函數對象本身。

雖然不用高階函數依靠循環也能實現上述功能,但是作為高階函數可以計算任意復雜的函數,也體現了高階函數的價值。

Array.prototype.reduce

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

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
 

總結

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


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

 

轉自掘金,原鏈接https://juejin.im/post/5daf0af4f265da5bbb1e57c0


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM