函數式編程(一)

引言

javascript是一門多範式編程語言,什麼叫多範式?通俗一點來說,無論是爛大街的面向對象,仍是面向切面、函數式編程啥都能寫。函數式編程不是用函數來編程,其主旨是將複雜的函數轉化爲簡單的函數。這兩年隨着React的火熱,函數式編程的概念也開始流行起來,RxJS、cycleJS、lodashJS、underscoreJS等多種開源庫都使用了函數式的特性,可是相信絕大部分人看完有關函數式編程的書籍,仍是一臉懵逼。因此下面用我一年級的智商對函數式編程的理解,來介紹一些函數式編程的知識和概念。javascript

純函數

純函數的定義是,對於相同的輸入,永遠會獲得相同的輸出,並且沒有任何可觀察的反作用,也不依賴外部環境的狀態。java

var xs = [1,2,3,4,5];

// 純的
xs.slice(0,3);
//=> [1,2,3]

// 不純的,改變了原數組的值
xs.splice(0,3);
//=> [1,2,3]

大多數有用的純函數都應有至少一個參數。全部有用的純函數都應該返回一些東西。數據庫

let addNoReturn = (x, y) => {
    let z = x+ y
}
//無用的純函數

如今你能夠嘗試打開瀏覽器的控制檯,執行這樣一個函數編程

let add = (x, y) =>  x + y 
add(1, 2) //3

執行一次,結果是3。
如今你能夠再次執行一次數組

add(1, 2) //3

結果仍是3,再執行一次瀏覽器

add(1, 2) //3

結果仍是3,驚不驚喜,意不意外?
再看下面一個函數緩存

let wirteFile = (x) => {
      localStorage.setItem('font', '1')
      return x;
}

這個是純函數嗎,相同的結果也是相同的輸出啊?
顯然這個不是純函數,純函數不能修改任何外部變量,純函數沒有函數反作用
反作用可能包含,但不限於:app

  1. 更改文件系統編程語言

  2. 往數據庫插入記錄函數式編程

  3. 發送一個 http 請求

  4. 打印/log

  5. DOM 查詢

看到這裏你可能會把我拉黑,只有純函數我還怎麼寫代碼,怎麼完成需求?
在函數式編程中,你不單單編寫純函數。
函數式語言不能消除函數反作用,它們只能限制函數反作用。由於程序必須和真實世界交互,每個程序總有一些部分必須是不純的。目標是減小不純代碼的數量並將它們和咱們程序中的其餘部分隔離。

純函數不只下降了系統的複雜度,還有不少很棒的特性,好比可緩存性

const memorize = f => {
  const cache = {};

  return function() {
    const arg_str = JSON.stringify(arguments);
    cache[arg_str] = cache[arg_str] || f.apply(f, arguments);
    return cache[arg_str];
  };
};

const addNumber = memorize( x => x + 1)

//第一次計算慢
addNumber(1)
//第二次有了緩存,速度快了很多
addNumber(1)

咱們不用每次都本身實現memorize函數,lodash、ramda都提供了很好的封裝。

相關文章
相關標籤/搜索