一:什么是可选链操作符?

可选链操作符(  ?.  )允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。?. 操作符的功能类似于 . 链式操作符,不同之处在于,在引用为空(nullish ) (null 或者 undefined) 的情况下不会引起错误,该表达式短路返回值是 undefined。与函数调用一起使用时,如果给定的函数不存在,则返回 undefined

通俗来讲undefined。

二:&&操作符和可选链操作符的对比

let  deepObj ={
        fruit:{
           onTheTree:{
              apple:"苹果",
              color:["red","green"],
              type:"红富士"
           },
           onTheGround:{
             blueberry:"蓝莓",
             color:["blue","purple"],
             type:null
           },
           eat:function(){
            console.log('eat fruit~~~~~')
           }
        }
  }

假设我们要获取deepObj这个对象中蓝莓的类型以及苹果的大小

//使用 && 操作符
 let blueberryType = deepObj.fruit && deepObj.fruit.onTheGround && deepObj.fruit.onTheGround.type;
 console.log(blueberryType)   //打印 null
 let appleSize = deepObj.fruit && deepObj.fruit.onTheTree && deepObj.fruit.onTheTree.size;   
 console.log(appleSize)  //  打印 undefined
//使用可选链操作符 
 let blueberryType = deepObj.fruit?.onTheGround?.type;
 console.log(blueberryType)  //打印 null
 let appleSize = deepObj.fruit?.onTheTree?.size;
 console.log(appleSize) //打印 undefined

假设我们要获取到deepObj这个对象中的蓝莓: 我们需要进行判断 否则可能会出现错误。

//使用 && 操作符
  let blueberry = deepObj.fruit && deepObj.fruit.onTheGround && deepObj.fruit.onTheGround.blueberry || ''
  //使用可选链操作符
  let blueberry = deepObj.fruit?.onTheGround?.blueberry || ''

这样一对比 我们可以看出 可选链大大降低了代码量并且提高了代码的可读性。

三:函数调用、表达式、空值合并操作符

可选链操作符不仅仅可以操作对象数组它还可以操作函数和表达式

//可选链操作符操作函数
deepObj.fruit?.eat?.()  //控制台打印出 "eat fruit~~~~~"
console.log(deepObj.fruit?.buy?.()) //控制台打印出undefined
//可选链操作符操作表达式
function getObj(postion){
 const res = deepObj.fruit?['onThe'+postion]?.apple
 console.log(res)
}
 getObj('Tree')   //打印 "苹果"
 getObj('Ground') //打印 "undefined"

有时候深层对象中可能并没有我们要的那个值 或者这个值返回给你的是null 那么我们一般都不希望前端渲染时出现undefined和null 因此 我们可以提供一个默认值 在日常使用中 我们通常使用的是 或者运算符(||)来提供一个默认值。

可选链操作符中我们可以使用空值合并操作符来提供一个默认值 ??

let obj = deepObj.fruit?.onTheGround?.size??'small'
 console.log(obj) // 打印 "small"

四:注意事项!!

可选链操作符不能用于赋值

let obj = {}
obj?.property = 1
//控制台 Uncaught SyntaxError: Invalid left-hand side in assignment