摘要:由于是以空函數為代理對象,我們可以將執行它,觸發。中會遍歷數組依次取值,如果發現無法繼續取值則,跳出循環。
本文來自我的博客,歡迎大家去GitHub上star我的博客
我們在取值特別是鏈式取值的時候,常常會遇到Cannot read property "xx" of undefined的錯誤,如何避免這種情況的發生呢?這里有幾種方法以供參考
使用成熟的庫方法這是最簡單的一種手段:只用引入lodash,使用_.get方法;或者引入Ramda,使用R.path方法,我們就能規避出現上述錯誤的風險
盡管這種方法十分奏效且方便,但我還是希望你能看完其他方法
巧用&&和||我們知道,在JavaScript中,使用&&或者||操作符,最后返回的值不一定是boolean類型的,比如下面這個例子:
console.log(undefined && "a"); //undefined console.log("a" && "b"); //b console.log(undefined || "a"); //a console.log("a" || "b"); //a
&&:如果第一項是falsy(虛值,Boolean上下文中已認定可轉換為‘假‘的值),則返回第一項,否則返回第二項
||:如果第一項是falsy,返回第二項,否則返回第一項
我們可以利用這種規則進行取值
我們先擬一個數據
const artcle = { authorInfo: { author: "Bowen" }, artcleInfo: { title: "title", timeInfo: { publishTime: "today" } } };
接下來利用&&和||進行安全取值:
console.log(artcle.authorInfo && artcle.authorInfo.author); //Bowen console.log(artcle.timeInfo && artcle.timeInfo.publishTime); //undefined console.log(artcle.artcleInfo && artcle.artcleInfo.timeInfo && artcle.artcleInfo.timeInfo.publishTime ); //today console.log((artcle.authorInfo || {}).author); //Bowen console.log((artcle.timeInfo || {}).publishTime); //undefined console.log(((artcle.artcleInfo || {}).timeInfo || {}).publishTime); //today
不難看出,這兩種方法都不算優雅,只適用短鏈式取值,一旦嵌套過深,使用&&需要寫一長段代碼,而使用||需要嵌套很多括號
利用解構賦值的默認值我們可以利用es6的解構賦值,給屬性一個默認值,避免出現錯誤。以上文的artcle數據為例,如下:
const { authorInfo: { author } = {} } = artcle; console.log(author); //Bowen
上面這么做會暴露很多變量出來,我們可以簡單地封裝一個函數,如下:
const getAuthor = ({ authorInfo: { author } = {} } = {}) => author; console.log(getAuthor(artcle)); //Bowen
這樣做不會將變量暴露出來,同時getAuthor函數也能復用,優雅多了
利用try catch既然在取值的過程中會出現錯誤,那我們自然可以利用try catch提前將錯誤捕獲:
let author, publishTime; try { author = artcle.authorInfo.author; } catch (error) { author = null; } try { publishTime = artcle.timeInfo.publishTime; } catch (error) { publishTime = null; } console.log(author); //Bowen console.log(publishTime); //null
這個方法不好的地方在于:我們無法在一個try catch語句里進行多次取值,因為只要有任一錯誤,就會進入catch語句中去
我們可以寫一個通用函數優化這一流程:
const getValue = (fn, defaultVaule) => { try { return fn(); } catch (error) { return defaultVaule; } }; const author = getValue(() => artcle.authorInfo.author); const publishTime = getValue(() => artcle.timeInfo.publishTime); console.log(author); //Bowen console.log(publishTime); //undefined利用proxy
這是我在網上看到的一個十分有意思的寫法,利用了es6中的proxy完成的:
const pointer = function(obj, path = []) { return new Proxy(function() {}, { get: function(target, key) { return pointer(obj, path.concat(key)); }, apply: function(target, object, args) { let value = obj; for (let i = 0; i < path.length; i++) { if (value == null) { break; } value = value[path[i]]; } if (value === undefined) { value = args[0]; } return value; } }); }; const proxyArtcle = pointer(artcle); console.log(proxyArtcle.authorInfo.author()); //Bowen console.log(proxyArtcle.publishTime()); //undefined
原理比較簡單,我們可以看到,pointer方法返回的是一個以空函數為代理對象的Proxy實例,而在每次取值的時候會將key保存下來,以proxyArtcle.authorInfo.author為例,它其實等價于pointer(artcle, ["authorInfo", "author"])。由于是以空函數為代理對象,我們可以將執行它,觸發apply。apply中會遍歷path數組依次取值,如果發現無法繼續取值則break,跳出循環。
如果你還沒有學習proxy,可以花幾分鐘了解一下:proxy
這種方法在我看來已是比較優雅的解決方法,但由于proxy對瀏覽器和node版本有所限制,且不可能有polyfill,真正應用起來需要考慮太多
optional chaining這是一個新特性,尚在提案階段,具體可以看tc39/proposal-optional-chaining,不過已經有babel可以使用了:babel-plugin-proposal-optional-chaining
我們可以像下面一樣使用這個特性:
console.log(artcle?.authorInfo?.author); //Bowen console.log(artcle?.timeInfo?.publishTime) //undefined
這種方法已接近完美,我們可以期待它的真正落實
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/101957.html
摘要:技術棧問題描述在狀態組件中書寫下的其中涉及點擊某處出現彈框的操作,在中有選框,點擊取消或清空所有表單信息。點擊選框內的各個選項,報錯。在點擊取消之后,清空的是所有組件的內容,再打開新的彈窗后,組件的狀態并沒有刷新。 技術棧: react + dva + antd 問題描述: 在狀態組件中書寫state下的columns,其中涉及點擊某處出現彈框modal的操作,在modal中有sel...
摘要:最近啟動項目報了個錯誤,如下原因是在中使用了而在中已被刪除了 最近啟動vue-cli3.0項目報了個錯誤,如下showImg(https://segmentfault.com/img/bVbt7w8?w=2088&h=538);原因是在vue.config.js 中使用了 process.env.target 而在.env中 target已被刪除了
摘要:踩坑最近通過安裝擴展時,提示以下錯誤根據提示,通過以下方式安裝后,再次使用安裝,仍然是提示同樣的錯誤問題解決通過安裝的路走不通,還是得通過簡單暴力方式解決,使用源碼包通過編譯方式進行安裝編譯安裝前先安裝下載源代碼包后,在終端進入源碼目錄,執 踩坑 最近通過pecl安裝mongodb擴展時,提示以下錯誤 ...... configure: error: Cannot find OpenS...
摘要:根據當時的情境,是在微信開發者工具中刪掉該小程序然后重新載入就解決了,大家給出的結論是微信小程序開發者工具的。 Created 2019-4-2 22:17:34 by huqiUpdated 2019-4-2 23:17:34 by huqishowImg(https://segmentfault.com/img/bVbqOLH?w=1526&h=818); ↑開局一張圖,故事全靠編...
閱讀 3044·2021-11-19 11:31
閱讀 3129·2021-09-02 15:15
閱讀 985·2019-08-29 17:22
閱讀 1058·2019-08-29 16:38
閱讀 2464·2019-08-26 13:56
閱讀 833·2019-08-26 12:16
閱讀 1435·2019-08-26 11:29
閱讀 929·2019-08-26 10:12