摘要:前言在學習前端的時候,我總是能聽到很多高級詞匯,比如今天會聊到的函數式編程高階函數。接下來我們看看,高階函數有可能會遇到的問題,又如何去解決。
前言
在學習前端的時候,我總是能聽到很多高級詞匯,比如今天會聊到的 函數式編程(Functional Programming) & 高階函數 (Higher-order function) 。
但是當你真正的理解什么是 函數式編程 & 高階函數 的時候,也許會發現,你幾乎每天都會用到它,只是你不知道那就是高階函數 / 函數式編程。
在 javascript 中,函數是一種值,舉個例子:
const double = function (x) { return x * 2 }
我們把一個函數作為值,賦給了變量 double ,這在我們的代碼中很常見對嗎?
你是不是經常會聽到或者看到這樣一句話:“在 JavaScript 中函數是一等公民”
粗看很不好理解,但是它的意思很簡單:函數和 字符串/number 沒有什么不一樣,它可以聲明為變量,也可以作為參數傳入到其他函數中。
什么是高階函數?什么是高階函數?其實上一段我們已經說過了,我們可以把函數A作為參數傳入到另一個函數B中,那么接收函數作為參數的函數B,就是 高階函數 ,這只是方便大家理解,高階函數的定義是:
"一個函數的參數是另一個函數,或者一個函數的返回值是另一個函數"
高階函數的例子 filter說到 filter() 你肯定不陌生,他接收一個回調函數作為它的參數,所以它是一個典型的高階函數,舉個例子:
我們有這么一個數組,要篩選出對應 category 為 html&css 的書籍。
const books = [ {name:"gitbook",category:"git"}, {name:"reactbook",category:"react"}, {name:"vuebook",category:"vue"}, {name:"cssbook",category:"html&css"}, {name:"htmlbook",category:"html&css"}, ]
傳統的寫法是這樣:
let html_css_books = [] for (let i = 0; i < books.length; i++) { if(books[i].category === "html&css"){ html_css_books.push(books[i]) } } console.log(html_css_books)
我相信幾乎沒有人會選擇上面的方式,大部分人都會用 filter
const html_css_books = books.filter(function(item){return item.category === "html&css"})
當然我們還可以用箭頭函數來縮減一些代碼:
const html_css_books = books.filter(item => item.category === "html&css")
我知道這是一個大家都明白的例子,從這里你能看到幾個高階函數的好處?
更短的代碼
更少的錯誤
更多的復用
第三點你可能不同意,因為你可能會說,我們沒有復用任何代碼啊?但如果我們把傳入的filter的回調函數抽離出來呢?因為真正決定要過濾哪些數據的是這個部分。
const is_html_css_books = item => item.category === "html&css" const is_git_books = item => item.category === "git" const is_not_git_books = item => item.category !== "git" const html_css_books = books.filter(is_html_css_books) const git_books = books.filter(is_git_books) const not_git_books = books.filter(is_not_git_books)
清晰又簡潔不是嗎?
filter & map & find & reduce這些都是我們常見的高階函數,但是它們的用法各不相同
函數 | 返回值 |
---|---|
filter | 大數組 => 小數組 |
map | 數組 => 長度相等的數組 |
find | 數組 => 單個元素 |
reduce | 數組 => 大數組/小數組/單個元素/長度相等的數組/字符串/Number/其他值 |
reduce 有很多玩法,甚至它可以取代我們剛剛說的三種高階函數,下一篇我們會聊聊 reduce 的內容。接下來我們看看,高階函數有可能會遇到的問題,又如何去解決。
問題 & 解決 問題我們一起來看這樣一個場景
比如我們需要計算 a, b 兩個值的和的兩倍再加3,我們可能會定義兩個函數
function double(a, b) { return (a + b) * 2 } function add3(a) { return a + 3 }
那么我們會這樣調用:
add3(double(1,3))
但是如果我們需要多加幾次3呢?
add3(add3(add3(add3(add3(double(1,3))))))
是的,雖然計算沒有錯誤,但是我們的可讀性大大降低了,那面對這樣的情況如何處理呢?
解決:鏈式優化解決嵌套的第一種方法,就是拆解嵌套,鏈式調用,就像一條鏈子一樣,一環套一環,將上次的結果,作為下次的參數。
const chainObj = { double(a,b) { this.temp = (a + b) * 2; return this; }, add3() { this.temp += 3; return this; }, getValue() { const value = this.temp; // 記得這里要初始化temp值 this.temp = undefined; return value; } };
所以我們上面的嵌套現在可以這樣寫:
chainObj.double().add3().add3().add3().add3().getValue()Promise
上節的這段代碼
chainObj.double().add3().add3().add3().add3().getValue()
對比 Promise 的代碼
promise.then(fn).then(fn)...
是不是很像呢?是的沒錯,我們平時寫的 promise 其實都是在處理我們的 高階函數 的執行順序。
那么 Promise 又是如何實現這樣的鏈式調用的呢?下一次和大家分享~
最后這里是 Dendoink
奇舞周刊原創作者
掘金 [聯合編輯 / 小冊作者]
segmentfault [漫談前端 / 系列作者]
公眾號 [前端惡霸 / 主筆]
對于技術人而言:技 是單兵作戰能力,術 則是運用能力的方法。得心應手,出神入化就是 藝 。在前端娛樂圈,我想成為一名出色的人民藝術家。
掃碼關注公眾號 前端惡霸 我在這里等你:
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/104395.html
摘要:數據的層級意味著迭代數據結構并提取它的數據。對于技術人而言技是單兵作戰能力,術則是運用能力的方法。在前端娛樂圈,我想成為一名出色的人民藝術家。 聊聊 for of 說起 for of 相信每個寫過 JavaScript 的人都用過 for of ,平時我們用它做什么呢?大多數情況應該就是遍歷數組了,當然,更多時候,我們也會用 map() 或者 filer() 來遍歷一個數組。 但是就...
摘要:你能學到什么如何使用實現異步編程異步編程的原理解析前言結合上一篇文章,我們來聊聊基礎原理說到異步編程,你想到的是和,但那也只是的語法糖而已。表示一個異步操作的最終狀態完成或失敗,以及其返回的值。至此實現異步操作的控制。 你能學到什么 如何使用 Generator + Promise 實現異步編程 異步編程的原理解析 前言 結合 上一篇文章 ,我們來聊聊 Generator 基礎原理...
摘要:能幫我們解決什么痛點實現異步執行,在未出現前,我們通常是使用嵌套的回調函數來解決的。那么,接下來我們看一下使用的實例可以傳入兩個參數表示兩個狀態的回調函數,第一個是,必選參數第二個是,可選參數的方便之處。 深入理解promise 對于現在的前端同學來說你不同promise你都不好意思出門了。對于前端同學來說promise已經成為了我們的必備技能。 那么,下面我們就來說一說promise...
閱讀 855·2021-11-25 09:43
閱讀 3688·2021-11-19 09:40
閱讀 890·2021-09-29 09:34
閱讀 1799·2021-09-26 10:21
閱讀 880·2021-09-22 15:24
閱讀 4201·2021-09-22 15:08
閱讀 3279·2021-09-07 09:58
閱讀 2686·2019-08-30 15:55