函數式編程(二)—— 純函數

目錄

  • 純函數數據庫

    • 純函數的概念
    • Lodash——純函數的表明npm

      • 體驗Lodash
    • 純函數的好處編程

      • 可緩存
      • 可測試
      • 並行處理
    • 反作用
    • 【函數式編程整體設計】
以前講了函數的前置知識,若是仍是不太明白的同窗能夠參考文章 函數式編程(一)—— 前置知識 ,下面咱們能夠進行函數式編程的基礎內容。

純函數

純函數的概念

相同的輸入永遠會獲得相同的輸出,並且沒有任何可觀察的反作用。segmentfault

純函數就相似數學中的函數(用來描述輸入和輸出之間的關係),y = f(x)數組

let numbers = [1, 2, 3, 4, 5] 
// 純函數 
// 對於相同的函數,輸出是同樣的

// slice方法,截取的時候返回截取的函數,不影響原數組
numbers.slice(0, 3) // => [1, 2, 3] 
numbers.slice(0, 3) // => [1, 2, 3] 
numbers.slice(0, 3) // => [1, 2, 3] 

// 不純的函數 
// 對於相同的輸入,輸出是不同的

// splice方法,返回原數組,改變原數組
numbers.splice(0, 3) // => [1, 2, 3] 
numbers.splice(0, 3) // => [4, 5] 
numbers.splice(0, 3) // => []

// 下面函數也是純函數 
function getSum (n1, n2) {
    return n1 + n2
}
console.log(getSum(1, 2)) // 3
console.log(getSum(1, 2)) // 3
console.log(getSum(1, 2)) // 3
  • 函數式編程不會保留計算中間的結果,因此變量是不可變的(無狀態的)
  • 咱們也能夠把一個函數的執行結果交給另外一個函數處理

Lodash——純函數的表明

  • lodash 是一個純函數的功能庫,提供了模塊化、高性能以及一些附加功能。提供了對數組、數字、對象、字符串、函數等操做的一些方法

體驗Lodash

  • 安裝

新建文件夾 -> npm init -y -> npm i lodash緩存

  • 體驗
const _ = require('lodash')

const array = ['jack', 'tom', 'lucy', 'kate']

// head的別名是first  _.head(array)也能夠
console.log(_.first(array)) //jack
console.log(_.last(array)) //kate

console.log(_.toUpper(_.first(array))) //JACK

console.log(_.reverse(array))  //[ 'kate', 'lucy', 'tom', 'jack' ]
// 數組的翻轉不是純函數,由於會改變原數組。這裏的reserve是使用了數組的reverse,因此也不是純函數

const r = _.each(array, (item, index) => {
  console.log(item, index)
  // kate 0
  // lucy 1
  // tom 2
  // jack 3
})
console.log(r) // [ 'kate', 'lucy', 'tom', 'jack' ]

純函數的好處

可緩存

由於對於相同的輸入始終有相同的結果,那麼能夠把純函數的結果緩存起來,能夠提升性能。安全

const _ = require('lodash')

function getArea(r) {
  console.log(r)
  return Math.PI * r * r
}

let getAreaWithMemory = _.memoize(getArea)
console.log(getAreaWithMemory(4))
console.log(getAreaWithMemory(4))
console.log(getAreaWithMemory(4))
// 4
// 50.26548245743669
// 50.26548245743669
// 50.26548245743669

// 看到輸出的4只執行了一次,由於其結果被緩存下來了

那咱們能夠模擬一個記憶函數多線程

function memoize (f) {
  let cache = {}
  return function () {
    // arguments是一個僞數組,因此要進行字符串的轉化
    let key = JSON.stringify(arguments)
    // 若是緩存中有值就把值賦值,沒有值就調用f函數而且把參數傳遞給它
    cache[key] = cache[key] || f.apply(f,arguments)
    return cache[key]
  }
}

let getAreaWithMemory1 = memoize(getArea)
console.log(getAreaWithMemory1(4))
console.log(getAreaWithMemory1(4))
console.log(getAreaWithMemory1(4))
// 4
// 50.26548245743669
// 50.26548245743669
// 50.26548245743669

可測試

純函數讓測試更加的方便app

並行處理

  • 多線程環境下並行操做共享的內存數據極可能會出現意外狀況。純函數不須要訪問共享的內存數據,因此在並行環境下能夠任意運行純函數
  • 雖然JS是單線程,可是ES6之後有一個Web Worker,能夠開啓一個新線程

反作用

反作用就是讓一個函數變得不純,純函數的根據市相同的輸入返回相同的輸出,若是函數依賴於外部的狀態就沒法保證輸出相同,就會帶來反作用,以下面的例子:模塊化

// 不純的函數,由於它依賴於外部的變量
let mini = 18 
function checkAge (age) { 
    return age >= mini 
}

反作用來源:

  • 配置文件
  • 數據庫
  • 獲取用戶的輸入
  • ......

全部的外部交互都有可能帶來反作用,反作用也使得方法通用性降低不適合擴展和可重用性,同時反作用會給程序中帶來安全隱患給程序帶來不肯定性,可是反作用不可能徹底禁止,咱們不能禁止用戶輸入用戶名和密碼,只能儘量控制它們在可控範圍內發生。

函數式編程整體設計

相關文章
相關標籤/搜索