摘要:如果這個(gè)結(jié)構(gòu)非常復(fù)雜,那么想要安全優(yōu)雅地取出一個(gè)值,也并非簡(jiǎn)單。這是為了在對(duì)象中相關(guān)取值的過(guò)程,需要驗(yàn)證每一個(gè)和的存在性。并且這個(gè)數(shù)據(jù)結(jié)構(gòu)必然是動(dòng)態(tài)生成的,存在有時(shí)有時(shí)的情況。在測(cè)試過(guò)程中,很難復(fù)現(xiàn)。
古有趙子龍面對(duì)“沖鋒之勢(shì),有進(jìn)無(wú)退,陷陣之志,有死無(wú)生”的局面,能萬(wàn)軍叢中取敵將首級(jí)。
在我們的Javascript中,往往用對(duì)象(Object)來(lái)存儲(chǔ)一個(gè)數(shù)據(jù)結(jié)構(gòu)。如果這個(gè)結(jié)構(gòu)非常復(fù)雜,那么想要安全優(yōu)雅地取出一個(gè)值,也并非簡(jiǎn)單。
這篇文章將會(huì)詳細(xì)闡述在一個(gè)嵌套較深的場(chǎng)景中,如何安全的完成讀寫(xiě)操作。先后會(huì)嘗試多種方法,希望對(duì)讀者有所啟發(fā)。
本文示例借鑒A.Sharif的最新文章:Safely Accessing Deeply Nested Values In JavaScript,喜歡看英文原版的同學(xué)可以直接戳鏈接。
場(chǎng)景介紹在React開(kāi)發(fā)中,我們根據(jù)數(shù)據(jù)來(lái)渲染視圖。經(jīng)常會(huì)出現(xiàn)類(lèi)似下面這種情況:
const props = { user: { posts: [ { title: "Foo", comments: [ "Good one!", "Interesting..." ] }, { title: "Bar", comments: [ "Ok" ] }, { title: "Baz", comments: []} ], comments: [...] } }
這是一個(gè)典型的獲取用戶評(píng)論信息并加以展示的場(chǎng)景。其實(shí),這還嵌套的不夠深,試想一個(gè)回復(fù)存在多層:回復(fù)的回復(fù),回復(fù)的回復(fù)的回復(fù)。。。
姑且先看我們的示例吧,此時(shí)我們想獲取第一個(gè)post的評(píng)論信息。用傳統(tǒng)的javascript方法應(yīng)該這么做:
props.user && props.user.posts && props.user.posts[0] && props.user.posts[0].comments
也許經(jīng)驗(yàn)豐富的javascript開(kāi)發(fā)者會(huì)明白使用這么多&&的意義。這是為了在對(duì)象中相關(guān)取值的過(guò)程,需要驗(yàn)證每一個(gè)key和index的存在性。否則會(huì)有報(bào)錯(cuò),這將會(huì)是致命性的。并且props這個(gè)數(shù)據(jù)結(jié)構(gòu)必然是動(dòng)態(tài)生成的,存在有時(shí)valid有時(shí)invalid的情況。在測(cè)試過(guò)程中,很難復(fù)現(xiàn)。
同樣的尷尬場(chǎng)景比比皆是,想象一下,如果我們需要獲取一名用戶最后一個(gè)評(píng)論博客的題目,就需要:
props.user && props.user.comments && props.user.comments[0] && props.user.comments[0].blog.title
這些例子夸張嗎?其實(shí)不然。我們明白了,想要獲取一個(gè)數(shù)據(jù)值,需要一層一層遍歷屬性的存在性。這無(wú)疑是繁瑣的。
解決方案現(xiàn)在明白了我們面臨的困擾,接下來(lái)我會(huì)用幾種方法:
純JavaScript方法;
最具有函數(shù)式代表的JavaScript庫(kù)-Ramda,輔以柯?;╟urrying)等思想和方案解決問(wèn)題。
JavaScript方案先直接上代碼:
const get = (p, o) => p.reduce((xs, x) => (xs && xs[x]) ? xs[x] : null, o) console.log(get(["user", "posts", 0, "comments"], props)) // [ "Good one!", "Interesting..." ] console.log(get(["user", "post", 0, "comments"], props)) // null
注意這里我使用了一個(gè)ES5中,比較偏向函數(shù)式思想的reduce方法。關(guān)于這個(gè)方法,我想很多人其實(shí)還并不理解,建議先去進(jìn)行學(xué)習(xí),或者參考我之前的一篇文章。
同時(shí),我嘗試獲?。簎ser->posts[0]->comments,
并配以一個(gè)反例:user->post[0]->comments;
當(dāng)然,在反例中,post數(shù)組并不存在。
我們來(lái)分析一下代碼。
const get = (p, o) => p.reduce((xs, x) => (xs && xs[x]) ? xs[x] : null, o)
我們實(shí)現(xiàn)的get方法中,接收兩個(gè)參數(shù),第一個(gè)p表示獲取值的路徑(path);另外一個(gè)參數(shù)表示目標(biāo)對(duì)象。
同樣,為了設(shè)計(jì)上的更加靈活和抽象。我們可以柯粒化我們的方法:
const get = p => o => p.reduce((xs, x) => (xs && xs[x]) ? xs[x] : null, o)
這樣的話,就可以這個(gè)姿勢(shì)調(diào)用:
const getUserComments = get(["user", "posts", 0, "comments"]) console.log(getUserComments(props)) // [ "Good one!", "Interesting..." ] console.log(getUserComments({user:{posts: []}})) // null
如果關(guān)于get方法中reduce的使用還不清楚,那就再看一個(gè)簡(jiǎn)單的例子:
["id"].reduce((xs, x) => (xs && xs[x]) ? xs[x] : null, {id: 10}) // 返回10Ramda方案
如果不自己手動(dòng)設(shè)計(jì)上述方法的話,我們可以使用Ramda函數(shù)式類(lèi)庫(kù)完成:
const getUserComments = R.path(["user", "posts", 0, "comments"])
接下來(lái)調(diào)用需要這個(gè)姿勢(shì):
getUserComments(props) // [ "Good one!", "Interesting..." ] getUserComments({}) // null
如果我們想在指定路徑下未找到一個(gè)值時(shí),不返回null,而是返回自定義的內(nèi)容呢?我們可以使用pathOr方法,第一個(gè)參數(shù)用來(lái)設(shè)置默認(rèn)輸出。
const getUserComments = R.pathOr([], ["user", "posts", 0, "comments"]) getUserComments(props) // [ "Good one!", "Interesting..." ] getUserComments({}) // []總結(jié)
這篇文章翻譯自A.Sharif的最新文章:Safely Accessing Deeply Nested Values In JavaScript,其中后半部分未做翻譯。
后半部分其實(shí)分析了 Ramda+Folktale的實(shí)現(xiàn),以及Ramda+Lenses的實(shí)現(xiàn)。
Folktale和Lenses是非常函數(shù)式Functional Programming的思想,理解起來(lái)相對(duì)晦澀且比較小眾。有興趣的讀者可以點(diǎn)擊原文去自行了解。
Happy Coding!
如果你對(duì)函數(shù)式編程并不感冒,大可只學(xué)習(xí)第一部分的實(shí)現(xiàn)。對(duì)于函數(shù)式編程有興趣的同學(xué),希望這篇文章能夠拋磚引玉,歡迎與我交流。
PS: 作者Github倉(cāng)庫(kù),歡迎通過(guò)代碼各種形式交流。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/91679.html
摘要:如果這個(gè)結(jié)構(gòu)非常復(fù)雜,那么想要安全優(yōu)雅地取出一個(gè)值,也并非簡(jiǎn)單。這是為了在對(duì)象中相關(guān)取值的過(guò)程,需要驗(yàn)證每一個(gè)和的存在性。并且這個(gè)數(shù)據(jù)結(jié)構(gòu)必然是動(dòng)態(tài)生成的,存在有時(shí)有時(shí)的情況。在測(cè)試過(guò)程中,很難復(fù)現(xiàn)。 古有趙子龍面對(duì)沖鋒之勢(shì),有進(jìn)無(wú)退,陷陣之志,有死無(wú)生的局面,能萬(wàn)軍叢中取敵將首級(jí)。在我們的Javascript中,往往用對(duì)象(Object)來(lái)存儲(chǔ)一個(gè)數(shù)據(jù)結(jié)構(gòu)。如果這個(gè)結(jié)構(gòu)非常復(fù)雜,那么...
摘要:同行這么做使用實(shí)現(xiàn)圓形進(jìn)度條前端掘金在開(kāi)發(fā)微信小程序的時(shí)候,遇到圓形進(jìn)度條的需求。實(shí)現(xiàn)也談數(shù)組去重前端掘金的數(shù)組去重是一個(gè)老生常談的話題了。百度前端技術(shù)學(xué)院自定義前端掘金一標(biāo)簽概念元素表示用戶界面中項(xiàng)目的標(biāo)題。 閑話圖片上傳 - 掘金作者:孫輝,美團(tuán)金融前端團(tuán)隊(duì)成員。15年畢業(yè)加入美團(tuán),相信技術(shù),更相信技術(shù)只是大千世界里知識(shí)的一種,個(gè)人博客: https://sunyuhui.com ...
摘要:同行這么做使用實(shí)現(xiàn)圓形進(jìn)度條前端掘金在開(kāi)發(fā)微信小程序的時(shí)候,遇到圓形進(jìn)度條的需求。實(shí)現(xiàn)也談數(shù)組去重前端掘金的數(shù)組去重是一個(gè)老生常談的話題了。百度前端技術(shù)學(xué)院自定義前端掘金一標(biāo)簽概念元素表示用戶界面中項(xiàng)目的標(biāo)題。 閑話圖片上傳 - 掘金作者:孫輝,美團(tuán)金融前端團(tuán)隊(duì)成員。15年畢業(yè)加入美團(tuán),相信技術(shù),更相信技術(shù)只是大千世界里知識(shí)的一種,個(gè)人博客: https://sunyuhui.com ...
摘要:王國(guó)維在人間詞話里談到了治學(xué)經(jīng)驗(yàn),他說(shuō)古今之成大事業(yè)大學(xué)問(wèn)者,必經(jīng)過(guò)三種之境界。其中談到中凍結(jié)一個(gè)對(duì)象幾種由淺入深的實(shí)踐。王國(guó)維已先自表明,吾人可以無(wú)勞糾葛??偨Y(jié)本文先后介紹了關(guān)于凍結(jié)一個(gè)對(duì)象的三種進(jìn)階方法。 王國(guó)維在《人間詞話》里談到了治學(xué)經(jīng)驗(yàn),他說(shuō):古今之成大事業(yè)、大學(xué)問(wèn)者,必經(jīng)過(guò)三種之境界。 巧合的是,最近受 git chat / git book 邀請(qǐng),做了一個(gè)分享。其中談到J...
閱讀 3928·2021-11-24 09:38
閱讀 3110·2021-11-17 09:33
閱讀 3880·2021-11-10 11:48
閱讀 1248·2021-10-14 09:48
閱讀 3139·2019-08-30 13:14
閱讀 2559·2019-08-29 18:37
閱讀 3404·2019-08-29 12:38
閱讀 1423·2019-08-29 12:30