JavaScript?新提案optional?chaining可選鏈屬性原理詳解
Optional chaining
這是一項新的提案,老舊瀏覽器可能需要 polyfills。
Optional chaining ?.
(可選鏈,以下簡稱 OC)是一種以安全的方式去訪問嵌套的對象屬性,即使某個屬性根本就不存在。
起因:
一個在 JavaScript 中很常見的問題就是:假如用戶信息中,地址是可填可不填的,那我們就無法安全地訪問地址的某一個屬性:
let user = {}; // 用戶可能沒有填地址 alert(user.address.street); // 報錯
或者下面這種情況,在 WEB 開發(fā)中,我們可能需要去獲取一個 DOM 元素,但是這個 DOM 元素可能不存在:
// 當(dāng) querySelector(...) 的結(jié)果為 null 的時候,程序會報錯 let html = document.querySelector('.my-element').innerHTML;
在 OC ?.
出現(xiàn)之前,我們一般通過邏輯與操作來解決:
let user = {}; // 沒有地址的用戶 alert( user && user.address && user.address.street ); // undefined (不會報錯)
使用邏輯與操作符可以確保表達(dá)式的所有部分都能夠正確執(zhí)行,但是寫法卻比較笨重。
Optional chaining(可選鏈)
OC ?.
能夠使代碼變得簡便,當(dāng)位于其前的值為 undefined
或者是 null
時,會立即阻止代碼的執(zhí)行,并且返回 undefined
。
通過 OC,我們可以安全地訪問用戶的地址:
let user = {}; // 一個沒有地址的用戶 alert( user?.address?.street ); // undefined (不會報錯)
即使 user
對象不存在,使用 OC 訪問它的地址屬性也不會報錯:
let user = null; alert( user?.address ); // undefined alert( user?.address.street ); // undefined
需要注意的是,OC 僅允許它前面相鄰的部分為可選項,不包括進(jìn)一步的值。
在上面的代碼中,user?.
僅允許 user
這個對象為 null
或 undefined
。
另一方面,如果 user
這個對象真的存在,那么 user.address
這個屬性必須存在,否則訪問 user?.address.street
則會在第二個點這報錯。
不要過度使用 OC
我們應(yīng)該僅在希望某個值可能不存在的情況下才使用 ?.
例如,根據(jù)我們的代碼邏輯,user
對象必須存在,但是 address
屬性是可選的,所以 user.address?.street
才是更好的選擇。
所以,由于其他原因?qū)е碌?nbsp;user
對象為 undefined
的情況才能被快速發(fā)現(xiàn)。否則,bug 將會變得比較難找
位于 ?.
前的變量必須被顯示聲明
如果 user
這個變量根本沒有被聲明,那么 user?.anything
將會觸發(fā)一個錯誤:
// ReferenceError: user is not defined user?.address;
此處必須有變量聲明語句 let/const/var
, OC 對未聲明的變量無效
短路
在上文提到,在OC ?.
的前部分的值為 null
或 undefined
的時候,會立即停止執(zhí)行。
所以,如果在其后面如果有函數(shù)的調(diào)用,或者其他操作,都不會執(zhí)行。
let user = null; let x = 0; user?.sayHi(x++); // 什么都不會做 alert(x); // 0,值沒有自增
其他用法:?.(),?.[]
OC 不是一個操作符,而是一個特別的語法糖,所以可以和函數(shù)調(diào)用和中括號共用。
例如,?.()
可以用于執(zhí)行一個可能不存在的函數(shù)。
下面的代碼中,一些用戶擁有 admin
方法,一些用戶沒有:
let user1 = { admin() { alert("I am admin"); } }; let user2 = {}; user1.admin?.(); // I am admin user2.admin?.();
我們首先用點語法去獲取 admin
方法,因為 user 對象肯定存在,所以我們可以安全地去訪問;
然后使用 ?.()
檢查其左側(cè),如果 admin 這個方法存在,就執(zhí)行(例如 user1),否則就停止執(zhí)行,但是不報錯(例如 user2)。
?.
語法同樣可以在當(dāng)我們需要通過中括號去訪問屬性時使用,使用它可以安全的訪問一個或許還不存在的對象的屬性:
let user1 = { firstName: "John" }; let user2 = null; // 假如現(xiàn)在不能授權(quán)這個用戶 let key = "firstName"; alert( user1?.[key] ); // John alert( user2?.[key] ); // undefined alert( user1?.[key]?.something?.not?.existing ) // undefined
?.
同樣可以與 delete
操作符共用
delete user?.name; // 刪除用戶名,如果用戶存在的話
使用 ?.
可以進(jìn)行刪除和讀取操作,但是不能進(jìn)行賦值操作
在賦值運(yùn)算符的左側(cè),?.
無效
// 下面的代碼是假設(shè)現(xiàn)在需要在用戶存在的情況下,重新賦值 name 屬性 user?.name = "John"; // 報錯 // 等同于 undefined = "John"
總結(jié)
OC ?.
有三種形式:
obj?.prop
- 如果obj
存在的話,返回obj.prop
的值,否則返回undefined
;obj?.[prop]
- 如果obj
存在的話返回obj[prop]
的值,否則返回undefined
;obj?.method()
- 如果obj
存在的話則調(diào)用obj.method()
方法,否則返回undefined
。
這幾種形式都非常的直觀并且易于使用。?.
檢查左側(cè)的值是否為 null
或 undefine
,如果不是的話則繼續(xù)執(zhí)行。
通過鏈?zhǔn)降?nbsp;?.
可以安全地訪問嵌套的對象。
我們應(yīng)該僅在當(dāng)左側(cè)的值可能不存在的情況下才使用 ?.
,這樣在發(fā)生錯誤的時候才能更加容易找到問題。
參考鏈接:
https://javascript.info/optio...
https://developer.mozilla.org...
https://tc39.es/ecma262/#prod...
以上就是JavaScript 新提案optional chaining可選鏈的詳細(xì)內(nèi)容,更多關(guān)于JavaScript可選鏈的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
javascript動態(tài)創(chuàng)建對象的屬性詳解
在本篇文章中我們給大家分享了關(guān)于javascript動態(tài)創(chuàng)建對象的屬性的相關(guān)知識點以及代碼分享,需要的朋友們參考學(xué)習(xí)下。2018-11-11JavaScript實現(xiàn)找出數(shù)組中最長的連續(xù)數(shù)字序列
這篇文章主要介紹了JavaScript實現(xiàn)找出數(shù)組中最長的連續(xù)數(shù)字序列的方法,需要的朋友可以參考下2014-09-09layui實現(xiàn)數(shù)據(jù)表格table分頁功能(ajax異步)
這篇文章主要為大家詳細(xì)介紹了layui實現(xiàn)數(shù)據(jù)表格table分頁功能、異步加載,表格渲染,含條件查詢,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-07-07javascript驗證只能輸入數(shù)字和一個小數(shù)點示例
使用javascript限制只能輸入數(shù)字和一個小數(shù)點,在某些情況下還是比較使用的,下面有個不錯的示例,感興趣的朋友可以參考下2013-10-10