函數(shù)式編程

函數(shù)式編程與命令式編程

以函數(shù)式范式進(jìn)行開(kāi)發(fā)并不簡(jiǎn)單,關(guān)鍵在于習(xí)慣這種范式的機(jī)制。我們編寫一個(gè)例子來(lái)說(shuō)明差異。

假設(shè)我們想打印一個(gè)數(shù)組中所有的元素。我們可以用命令式編程,聲明的函數(shù)如下。

    const printArray = function(array) {
      for (var i = 0; i < array.length; i++){
        console.log(array[i]);
      }
    };
    printArray([1, 2, 3, 4, 5]);

在上面的代碼中,我們迭代數(shù)組,打印每一項(xiàng)。

現(xiàn)在,我們?cè)囍堰@個(gè)例子轉(zhuǎn)換成函數(shù)式編程。在函數(shù)式編程中,函數(shù)就是搖滾明星。我們關(guān)注的重點(diǎn)是需要描述什么,而不是如何描述?;氐竭@一句:“我們迭代數(shù)組,打印每一項(xiàng)?!蹦敲?,首先要關(guān)注的是迭代數(shù)據(jù),然后進(jìn)行操作,即打印數(shù)組項(xiàng)。下面的函數(shù)負(fù)責(zé)迭代數(shù)組。

    const forEach = function(array, action){
      for (var i = 0; i < array.length; i++){
        action(array[i]);
      }
    };

接下來(lái),要?jiǎng)?chuàng)建另一個(gè)負(fù)責(zé)把數(shù)組元素打印到控制臺(tái)的函數(shù)(考慮為回調(diào)函數(shù)),如下所示。

    const logItem = function(item) {
      console.log(item);
    };

最后,像下面這樣使用聲明的函數(shù)。

    forEach([1, 2, 3, 4, 5], logItem);

只需要上面這一行代碼,就能描述我們要把數(shù)組的每一項(xiàng)打印到控制臺(tái)。這是我們的第一個(gè)函數(shù)式編程的例子!

有以下幾點(diǎn)要注意。

  • 函數(shù)式編程的主要目標(biāo)是描述數(shù)據(jù),以及要對(duì)數(shù)據(jù)應(yīng)用的轉(zhuǎn)換。
  • 在函數(shù)式編程中,程序執(zhí)行順序的重要性很低;而在命令式編程中,步驟和順序是非常重要的。
  • 函數(shù)和數(shù)據(jù)集合是函數(shù)式編程的核心。
  • 在函數(shù)式編程中,我們可以使用和濫用函數(shù)和遞歸;而在命令式編程中,則使用循環(huán)、賦值、條件和函數(shù)。
  • 在函數(shù)式編程中,要避免副作用和可變數(shù)據(jù),意味著我們不會(huì)修改傳入函數(shù)的數(shù)據(jù)。如果需要基于輸入返回一個(gè)解決方案,可以制作一個(gè)副本并返回?cái)?shù)據(jù)修改后的副本。

ES2015+和函數(shù)式編程

有了ES2015+的新功能,用JavaScript進(jìn)行函數(shù)式編程就變得更加容易了。我們來(lái)看一個(gè)例子。

考慮我們要找出數(shù)組中最小的值。要用命令式編程完成這個(gè)任務(wù),只要迭代數(shù)組,檢查當(dāng)前的最小值是否大于數(shù)組元素;如果是,就更新最小值,代碼如下。

    var findMinArray = function(array){
      var minValue = array[0];
      for (var i=1; i<array.length; i++){
        if (minValue > array[i]){
          minValue = array[i];
        }
      }
      return minValue;
    };
    console.log(findMinArray([8,6,4,5,9])); // 輸出4

要用函數(shù)式編程完成相同的任務(wù),可以使用Math.min函數(shù),傳入所有要比較的數(shù)組元素。我們可以像下面的例子里這樣,使用ES2015的解構(gòu)運(yùn)算符(...),把數(shù)組轉(zhuǎn)換成單個(gè)的元素。

    const min_ = function(array){
          return Math.min(...array)
        console.log(min_([8,6,4,5,9])); // 輸出4

使用ES2015的箭頭函數(shù),可以進(jìn)一步簡(jiǎn)化上面的代碼。

    const min = arr => Math.min(...arr);
    console.log(min([8, 6, 4, 5, 9]));

JavaScript函數(shù)式工具箱——map、filter和reduce

map、filter和reduce函數(shù)(第3章已經(jīng)學(xué)習(xí)過(guò))是JavaScript函數(shù)式編程的基礎(chǔ)。

我們可以使用map函數(shù),把一個(gè)數(shù)據(jù)集合轉(zhuǎn)換或映射成另一個(gè)數(shù)據(jù)集合。先看一個(gè)命令式編程的例子。

    const daysOfWeek = [
      {name: 'Monday', value: 1},
      {name: 'Tuesday', value: 2},
      {name: 'Wednesday', value: 7}
    ];

    let daysOfWeekValues_ = [];
    for (let i = 0; i < daysOfWeek.length; i++) {
      daysOfWeekValues_.push(daysOfWeek[i].value);
    }

再以函數(shù)式編程并使用ES2015+語(yǔ)法來(lái)考慮同樣的例子,代碼如下。

    const daysOfWeekValues = daysOfWeek.map(day => day.value);
    console.log(daysOfWeekValues);

我們可以使用filter函數(shù)過(guò)濾一個(gè)集合的值。下面來(lái)看一個(gè)例子。

    const positiveNumbers_ = function(array){
      let positive = [];
      for (let i = 0; i < array.length; i++) {
        if (array[i] >= 0){
          positive.push(array[i]);
        }
      }
      return positive;
    }
    console.log(positiveNumbers_([-1,1,2, -2]));

我們可以把同樣的代碼寫成函數(shù)式的,如下所示。

    const positiveNumbers = (array) => array.filter(num => (num >= 0));
    console.log(positiveNumbers([-1,1,2, -2]));

我們也可以使用reduce函數(shù),把一個(gè)集合歸約成一個(gè)特定的值。比如,對(duì)一個(gè)數(shù)組中的值求和。

    const sumValues = function(array) {
      let total = array[0];
      for (let i = 1; i<array.length; i++) {
        total += array[i];
      }
      return total;
    };
    console.log(sumValues([1, 2, 3, 4, 5]));

上面的代碼也可以寫成這樣。

    const sum_ = function(array){
      return array.reduce(function(a, b){
          return a + b;
      })
    };
    console.log(sum_([1, 2, 3, 4, 5]));
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容