JavaScript 可選鏈操做符&&空值合併操做符

背景

最近 開始接觸到一些ES6之後的新特性 使用起來確實方便了很多markdown

尤爲是最近有一個項目 在方法中須要傳入index 可是在作非空驗證的時候 若是傳入的index是0 也會被判斷爲false 這就十分頭疼了app

冗餘的判斷不只使代碼的可讀性變差 並且會使代碼變得不簡潔ide

可是在接觸到可選鏈操做符後 emmmmm 這也太香了 避免了 && 和 多餘的非空校驗函數

因此決定以此爲開始 陸續的寫一些ES6 ES7...以後的新特性ui

可選鏈操做符

初識

這裏我引用一段MDN上的解釋lua

可選鏈操做符( ?. )容許讀取位於鏈接對象鏈深處的屬性的值,而沒必要明確驗證鏈中的每一個引用是否有效。?. 操做符的功能相似於 . 鏈式操做符,不一樣之處在於,在引用爲空(nullish ) (null 或者 undefined) 的狀況下不會引發錯誤,該表達式短路返回值是 undefined。與函數調用一塊兒使用時,若是給定的函數不存在,則返回 undefined。url

或許 你仍是?????spa

不要急 咱們來看一道例題3d

const adventurer = {
  name: '林克',
  weapon: {
    name: '大師劍'
  }
};

const weaponName = adventurer.weapon?.name;
console.log(weaponName);
// expected output: 大師劍

console.log(adventurer.savePrincess?.());
// expected output: undefined

const shieldName = adventurer.shield?.name;
console.log(shieldName);
// expected output: undefined
複製代碼

上述例子adventurer.weapon?.namecode

咱們試圖去尋找adventurer對象下的weapon屬性下的name屬性

adventurer對象有weapon屬性 因此返回咱們能夠取出咱們的大師劍

而後是adventurer.savePrincess?.()

顯然adventurer下沒有savePrincess這個方法 因此救公主??? 不存在的 直接返回undefined

最後是adventurer.shield?.name

一樣的 咱們發現 adventurer對象下也沒有shield屬性 因此直接返回undefined

好啦 至此 咱們大概理解了可選鏈是怎麼一回事

接下來 咱們來看看 可選鏈有什麼須要注意的地方

注意點

可選鏈不能用於賦值

let object = {};
object?.property = 1; // Uncaught SyntaxError: Invalid left-hand side in assignment
複製代碼

短路計算

當在表達式中使用可選鏈時,若是左操做數是 null 或 undefined,表達式將不會被計算,例如:

let potentiallyNullObj = null;
let x = 0;
let prop = potentiallyNullObj?.[x++];

console.log(x); // x 將不會被遞增,依舊輸出 0
複製代碼

最後再舉一個本身在實際開發中的例子

假若有一個方法setStudentResult(action) 它接收一個對象action

爲了讓咱們的代碼健壯 咱們必須在方法內部作出參數的非空校驗 顯然下面這樣是不行的

const list = {};

/** * @param {*} action */
function setStudent (action) {
  list[action.index] = action.student;
}
複製代碼

若是咱們直接調用setStudent() 顯然整個程序都會崩潰

因此在之前 咱們能夠將方法體改爲這樣

// 同時包含函數接收了action參數 而且參數中有咱們須要的內容
function setStudent(action) {
  if (action) {
    if (action.index && action.student) {
      list[action.index] = action.student;
    }
  }
}
複製代碼

可是 若是使用可選鏈操做符 咱們就能夠將方法定義成以下

function setStudent (action) {
  if (action?.index && action?.student) {
    list[action.index] = action.student;
  }
}
複製代碼

能夠看到 不管是可讀性 仍是簡潔程度 可選鏈操做符都更勝一籌

空值合併操做符

仍是引用一段MDN上解釋

空值合併操做符(??)是一個邏輯操做符,當左側的操做數爲 null 或者 undefined 時,返回其右側操做數,不然返回左側操做數。

對比 ||

咱們知道 || 邏輯或運算符 也具備類似的功能

也就是在 || 左側操做數爲假值時 會返回右側 操做數

JS中的假值有

  • 0

  • ''

  • NaN

  • null

  • undefined

因此設想一個場景 咱們對一個function中的參數使用 || 運算符 來判斷用戶是否輸入

function addNum(a,b) {
  var a = a || 0
  var b = b || 0
  return a + b 
}
複製代碼

上述代碼咱們用 || 運算符來判斷用戶 用戶輸入的合法性

可是這樣咱們就沒法排除 0 這種狀況

若是用戶就是輸入了0 可是0依舊是一個假值 因此仍是會返回 || 操做符右側是操做數

這就與咱們的預期不一致了

而 ?? 空值合併操做符就只是檢驗了 null 和 undefined

注意點

短路計算

與 OR 和 AND 邏輯操做符類似,當左表達式不爲 null 或 undefined 時,不會對右表達式進行求值

var a = 1;
undefined ?? a++;
console.log(a); // 1

var b = 1;
true ?? b++;
console.log(b); // 2
複製代碼

不能與 AND 或 OR 操做符共用

null || undefined ?? "foo"; // 拋出 SyntaxError
true || undefined ?? "foo"; // 拋出 SyntaxError
複製代碼

與可選鏈操做符連用

兩個操做符都是針對 undefined 和 null 兩個值

因此咱們能夠結合這兩個操做符

let customer = {
  name: "chou",
  details: { age: 100 }
};
let customerCity = customer?.city ?? "荒野之息";
console.log(customerCity); // 荒野之息
複製代碼
相關文章
相關標籤/搜索