摘要:在函數(shù)式編程中的錯誤處理,強壯代碼文章中所用的思路與本篇一樣,只不過在函數(shù)式編程中的錯誤處理,強壯代碼中可以認(rèn)為是以和作為標(biāo)識,而本篇多帶帶創(chuàng)造了標(biāo)識。使用本篇的方法重寫函數(shù)式編程中的錯誤處理,強壯代碼中的代碼參考資料函數(shù)式編程指南我在
以下代碼會用到函數(shù)組合函數(shù)compose,只要知道compose是干什么的就足夠了,如果好奇具體的實現(xiàn),可以看《JavaScript函數(shù)式編程之函數(shù)組合函數(shù)compose和pipe的實現(xiàn)》
管道是函數(shù)式編程中經(jīng)常使用的,很多時候我們需要按照條件判斷進(jìn)行組合函數(shù)的選擇,簡單的說就是從原來的一條管道變成兩條管道,根據(jù)判斷選擇進(jìn)入哪一條。
這里的關(guān)鍵在于,我們?nèi)绾闻袛嗌弦粋€函數(shù)的返回值應(yīng)該進(jìn)入哪一條管道?
let step1 = x => x ? 1 : 2; let step2 = x => x === 1 ? 3 : 4; let step3 = x => x === 3 ? 5 : 6; let getResult = compose(step3, step2, step1) let result = getResult(1);
這是最直接的方法,每一步根據(jù)返回值多帶帶判斷,如果step1的返回值發(fā)生了變化,下一步的判斷也需要跟著修改,這種寫法顯然不好。那我們能不能在返回值的基礎(chǔ)上加上一個標(biāo)識,專門用來做判斷?我們很自然的就會想到對象。
let step1 = x => { if (x) { return { value: 1, identity: "channelOne" } } else { return { value: 2, identity: "channelTwo" } } } let step2 = x => { if (x.identity === "channelOne") { return x.value = 3; } else { return x.value = 4; } } let step3 = x => { if (x.identity === "channelOne") { return x.value = 5; } else { return x.value = 6; } } let getResult = compose(step3, step2, step1); let result = getResult(1);
是不是好了很多?不過這依然要繼續(xù)改進(jìn)。當(dāng)我們需要使用forin等方式遍歷對象時,identity會被遍歷出來,一般情況下我們都希望它不會被遍歷,那就還需要把這個屬性定義為不可枚舉的。
修改step1并簡化代碼:
let step1 = x => { if (x) { let obj = {value: 1}; Object.defineProperty(obj, "identity", { enumerable: false, value: "channelOne" }); return obj; } else { let obj = {value: 2}; Object.defineProperty(obj, "identity", { enumerable: false, value: "channelTwo" }); return obj; } } let selectChannel = (fn1, fn2) => val => val.identity === "channelOne" ? fn1(val) : fn2(val); let getResult = compose( selectChannel( x => Object.defineProperty(x, "value", {value: 5}), x => Object.defineProperty(x, "value", {value: 6}) ), selectChannel( x => Object.defineProperty(x, "value", {value: 3}), x => Object.defineProperty(x, "value", {value: 4}) ), step1 ); let result = getResult(1);
在selectChannel中,函數(shù)會根據(jù)傳進(jìn)來的對象的標(biāo)識選擇執(zhí)行。至此,功能基本上實現(xiàn)了,可依然不夠好,代碼不夠簡潔優(yōu)雅,重用也可以繼續(xù)改進(jìn)。
用構(gòu)造函數(shù)做標(biāo)識
let channelOne = function(x) { this.value = x; }; channelOne.of = x => new channelOne(x); let channelTwo = function(x) { this.value = x; }; channelTwo.of = x => new channelTwo(x); let step1 = x => x ? channelOne.of(1) : channelTwo.of(2); let selectChannel = (fn1, fn2) => val => val.constructor === channelOne ? fn1(val) : fn2(val); let getResult = compose( selectChannel(x => channelOne.of(5), x => channelTwo.of(6)), selectChannel(x => channelOne.of(3), x => channelTwo.of(4)), step1 ); let result = getResult(1);
太棒了!
看到這里,有么有驚喜的發(fā)現(xiàn),if/else不見了?肯定會有人覺得我是一個換湯不換藥的奸商。雖然if/else不見了,可是我用了三元運算符,這在本質(zhì)上有什么區(qū)別?
答案是,沒區(qū)別,他們都是條件判斷,這是不可避免的。
我們不妨?xí)簳r把關(guān)注的焦點放在三元運算符與if/else的區(qū)別上面來。我們什么時候會使用三元運算符?是條件判斷很簡單的時候,簡單到只需要一個表達(dá)式,而不是復(fù)雜的操作。雖然三元運算符也可以用逗號隔開表達(dá)式從而進(jìn)行多個操作,可我們這個時候更愿意使用if/else。
說到這里就已經(jīng)很明顯了,這種構(gòu)造函數(shù)做標(biāo)識的方式,把復(fù)雜的條件判斷分解了,分解到在做判斷的時候只需要選擇方向,相關(guān)的操作可以扔到后面。
在《JavaScript函數(shù)式編程中的錯誤處理,強壯代碼》文章中所用的思路與本篇一樣,只不過在《JavaScript函數(shù)式編程中的錯誤處理,強壯代碼》中可以認(rèn)為是以null和undefined作為標(biāo)識,而本篇多帶帶創(chuàng)造了標(biāo)識。本篇中的方法更加的通用,因為null和undefined也可能是我們需要使用的值。
使用本篇的方法重寫《JavaScript函數(shù)式編程中的錯誤處理,強壯代碼》中的代碼
let channelError = function(x) { this.value = x; }; channelError.of = x => new channelError(x); let channelSuccess = function(x) { this.value = x; }; channelSuccess.of = x => new channelSuccess(x); let security= fn => val => val.constructor === channelError? val : fn(val); let validate1 = x => x ? channelSuccess.of(x) : channelError.of("validate1 is not passed!"); let validate2 = x => x.value ? x : channelError.of("validate2 is not passed!"); let handleError = x => { if (x.constructor === channelError) alert(x.value); }; let postData = () => axios.post(...); let getResult = compose( handleError, security(postData), security(validate2), security(validate1) );
參考資料:
JS函數(shù)式編程指南
我在github https://github.com/zhuanyongx...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/94281.html
摘要:函數(shù)式編程的定義函數(shù)是一段可以通過其名稱被調(diào)用的代碼。純函數(shù)大多數(shù)函數(shù)式編程的好處來自于編寫純函數(shù),純函數(shù)是對給定的輸入返回相同的輸出的函數(shù),并且純函數(shù)不應(yīng)依賴任何外部變量,也不應(yīng)改變?nèi)魏瓮獠孔兞俊? 一個持續(xù)更新的github筆記,鏈接地址:Front-End-Basics,可以watch,也可以star。 此篇文章的地址:JavaScript函數(shù)式編程入門經(jīng)典 正文開始 什么是函...
摘要:聲明式編程一種編程范式,與命令式編程相對立。常見的聲明式編程語言有數(shù)據(jù)庫查詢語言,正則表達(dá)式邏輯編程函數(shù)式編程組態(tài)管理系統(tǒng)等。函數(shù)式編程,特別是純函數(shù)式編程,嘗試最小化狀態(tài)帶來的副作用,因此被認(rèn)為是聲明式的。 編程范式與函數(shù)式編程 一、編程范式的分類 常見的編程范式有:函數(shù)式編程、程序編程、面向?qū)ο缶幊獭⒅噶钍骄幊痰取T诿嫦驅(qū)ο缶幊痰氖澜纾绦蚴且幌盗邢嗷プ饔茫ǚ椒ǎ┑膶ο螅–lass...
摘要:在函數(shù)式編程中數(shù)據(jù)在由純函數(shù)組成的管道中傳遞。函數(shù)式編程中函子是實現(xiàn)了函數(shù)的容器下文中將函子視為范疇,模型可表示如下但是在函數(shù)式編程中要避免使用這種面向?qū)ο蟮木幊谭绞饺《畬ν獗┞读艘粋€的接口也稱為。 showImg(https://segmentfault.com/img/remote/1460000018101204); 該系列會有 3 篇文章,分別介紹什么是函數(shù)式編程、剖析函數(shù)...
摘要:例如通過哈希表映射需要一個操作來檢查值是否相等,另一個操作用于創(chuàng)建哈希碼。如果使用哈希碼,則對象應(yīng)該是不可變的。模式匹配提案目前處于第階段。在本文,我們研究其中的智能管道另一個提議被稱為。更強大,更重量級,并附帶自己的數(shù)據(jù)結(jié)構(gòu)。 翻譯:瘋狂的技術(shù)宅原文:http://2ality.com/2019/01/fut... 本文首發(fā)微信公眾號:jingchengyideng歡迎關(guān)注,每天...
閱讀 1764·2021-09-28 09:43
閱讀 1116·2021-09-23 11:22
閱讀 2722·2021-09-14 18:05
閱讀 1826·2019-08-30 15:52
閱讀 2816·2019-08-30 10:55
閱讀 2013·2019-08-29 16:58
閱讀 1326·2019-08-29 16:37
閱讀 3037·2019-08-29 16:25