摘要:在學習的過程中時常會聽到一個名次函數式編程,那么究竟什么是函數式編程,函數式編程又有什么優點,這就在這篇博客進行一個簡單的總結吧主要內容函數式編程的概念函數式編程的優點與示例什么是函數式編程首先,我們放下編程的概念,我們來看函數。
在學習 JS 的過程中時常會聽到一個名次——“函數式編程”,那么究竟什么是函數式編程,函數式編程又有什么優點,這就在這篇博客進行一個簡單的總結吧~
主要內容:
函數式編程的概念
函數式編程的優點與示例
什么是函數式編程首先,我們放下編程的概念,我們來看函數。
函數的概念來自于數學,數學中的函數 f(x) = y 有一個非常重要的特點對于一個給定的 x,有唯一的 y 與其對應(這就是為什么橢圓曲線不是函數)
然而在編程中,函數并不具有這個特點,舉個栗子:
let val = 1
function add(x){
return x + val
}
console.log(add(1)) // 2
val += 1
console.log(add(1)) // 3
可以看到編程中的函數在參數相同的情況下,允許有不同的返回值——只要依賴于函數外部的量
那么當函數依賴于外部的變量(常量不會有這樣的問題),并且函數在多處調用,就有可能出現 bug,函數的調用結果可能會和預期結果相去甚遠
而函數式編程就要求我們規避這樣的情況,讓所有函數對于相同的輸入的返回值相同,這樣的特性就叫做引用透明性,這就是函數式編程的核心特性!
一個符合引用透明性的函數的栗子:
function id(x){ return x; }
函數式編程帶來的優點
在上文中提到過,編程語言中的函數大多是不滿足數學中的函數的概念的,so 我們將滿足數學函數條件的函數稱為“純函數”
可測試性函數式編程的優點大多都來自于純函數
除了測試人員進行的全方位測試外,我們在開發過程中往往要對自己寫的代碼進行模塊測試
在開發中,我受非純函數迫害已久,由于它依賴了外部變量(比如存儲在 localStorage 中的數據)我不得不三番五次去檢查這些外部變量是否在某個過程中被改變甚至是刪除
let val = 1
function add(x){
return x + val
}
console.log(add(1)) // 2
// 在未知因素影響下 val被改變
console.log(add(1)) // 預期結果 2,實際輸出 emmmmm
如果我沒有注意外部依賴而是一頭扎進函數邏輯里,可能永遠都找不到這個bug
代碼的并發性雖然我們都知道 JS 是一門單線程語言(關于JS的執行可以參見->技術總結——JS的執行順序),但是我們為了提高前端的性能可能會通過 WebWorker 來并發執行多個任務,或者在 Node 環境下 JS 并發執行函數
這個時候就是對非純函數的一個很大的考驗:
let global = "全局變量"
let func1 = ()=>{
global = "全局變量被改變了"
// 一些邏輯
}
let func2 = ()=>{
if(global = "全局變量"){
return true
}
}
上面的兩個函數都依賴于外部的global,當它們并發執行,func1就會對func2產生影響,如果將它們變為純函數就不會有這樣的問題:
let global = "全局變量"
let func1 = (x)=>{
x = "全局變量被改變了"
// 一些邏輯
}
let func2 = (x)=>{
if(x = "全局變量"){
return true
}
}
函數執行的緩存
當我們的函數都是純函數,而我們又會多次調用函數,我們就可以對函數對象進行一個緩存
比如我們需要大量計算數字的4次方,我們可以建立一個映射表用來緩存函數的執行結果:
// 映射表
let fourTimesTable = {};
let fourTimes = (x){
return x*x*x*x
}
// 檢查表中是否有 2 的四次方,如果有就返回,如果沒有就執行函數避免運算
fourTimesTable.hasOwnProperty(2)");2]:
fourTimesTable[2] = fourTimes(2)
管道與組合
管道過濾器是一種很經典的設計模式,我們可以將這種模式和函數式編程結合起來
在管道和過濾器軟件體系結構中,每個模塊都有一組輸入和一組輸出。每個模塊從它的輸入端接收輸入數據流,在其內部經過處理后,按照標準的順序,將結果數據流送到輸出端,以達到傳遞一組完整的計算結果實例的目的。
在這種結構中,各模塊之間的連接器充當了數據流的導管,將一個過濾器的輸出傳到下一個過濾器的輸入端。所以,這種連接器稱為“管道”。
我們也可以將這樣的私用運用在函數式編程中,將一個個函數作為過濾器,通過函數的組合,形成一條數據處理的通路:
// 參數累加
function add(...args){
let result = args.reduce((prev, cur, index, arr)=> {
return prev + cur;
})
return result
}
// 參數累乘
function times(...args){
let result = args.reduce((prev, cur, index, arr)=> {
return prev * cur;
})
return result
}
let arr1=[1,3,6],arr2=[2,5,21],arr3=[3,7,8,27,4]
// 三組數據,要求組內累乘,然后結果累加
add(times(...arr1),times(...arr2),times(...arr3))
// 三組數據,要求組內累加,然后結果累乘
times(add(...arr1),add(...arr2),add(...arr3))
對函數式編程的初探暫止于此,進一步學習后再做總結~
本文同步發布于我的個人博客,CSDN,掘金
如果有什么問題,意見,建議歡迎評論;如果覺得我寫的不錯,那就點個贊吧~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/7847.html
摘要:遍歷執行其中存儲的所有的匿名函數。如果我們使用一個類來管理相關依賴,這很接近的表現方式代碼看起來就像下面這樣你會發現現在匿名函數被儲存在而不是原來的。 許多前端框架(如Angular,React,Vue)都有自己的響應式引擎。通過理解如何響應,提議提升你的開發能力并能夠更高效地使用JS框架。本文中構建的響應邏輯與Vue的源碼是一毛一樣的! 響應系統 初見時,你會驚訝與Vue的響應系統。...
摘要:接收用戶請求并分析請求的。執行函數并生成響應,返回給瀏覽器。這個過程我們稱為注冊路由,路由負責管理和函數之間的映射,而這個函數則被稱為視圖函數。文件是一個名為的文本文件,它存儲了項目中提交時的忽略文件規則清單。 flask簡述 Flask 是一個基于 Python 開發并且依賴 jinja2 模板和 Werkzeug WSGI 服務的一個微型框架,對于 Werkzeug 本質是 Soc...
摘要:系列教程,持續更新系列教程應用初見系列教程處理靜態文件系列教程使用模板引擎系列教程路由控制中間件系列教程綜合搭建登錄注冊頁面系列教程實現登錄注冊功能這篇教程主要介紹構建服務器,簡單引用本教程的版本要格外注意版本號案例簡單利用搭建服務器文件夾 koa2系列教程,持續更新 koa2系列教程:koa2應用初見 koa2系列教程:koa2處理靜態文件 koa2系列教程:koa2使用模板引擎 ...
閱讀 2472·2021-09-29 09:34
閱讀 3308·2021-09-23 11:21
閱讀 2501·2021-09-06 15:00
閱讀 1128·2019-08-30 15:44
閱讀 2029·2019-08-29 17:23
閱讀 3001·2019-08-29 16:44
閱讀 3060·2019-08-29 13:13
閱讀 1939·2019-08-28 18:12