ES11(2020)可选链操作符和空值合并运算符

2022-07-18 14:17:31

可选链操作符 Optional chaining

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

当尝试访问可能不存在的对象属性时,可选链操作符将会使表达式更短、更简明。在探索一个对象的内容时,如果不能确定哪些属性必定存在,可选链操作符也是很有帮助的。

const adventurer={
  name:'Alice',
  cat:{
    name:'Dinah'}};// 直接操作未知的变量和方法有可能报错
console.log(adventurer.aa.bb)// Uncaught TypeError: Cannot read property 'bb' of undefined
console.log(adventurer.aa())// Uncaught TypeError: adventurer.aa is not a function// 使用可选链操作符可避免报错const dogName= adventurer.dog?.name;
console.log(dogName);// undefined

console.log(adventurer.someNonExistentMethod?.());// undefined

语法:

obj?.prop// 对象
obj?.[expr]// 对象
arr?.[index]// 数组
func?.(args)// 函数

通过连接的对象的引用或函数可能是undefinednull 时,可选链操作符提供了一种方法来简化被连接对象的值访问。

比如,思考一个存在嵌套结构的对象 obj。不使用可选链的话,查找一个深度嵌套的子属性时,需要验证之间的引用,例如:

// 以前的写法let nestedProp= obj.first&& obj.first.second;// 可选链操作符写法let nestedProp= obj.first?.second;

通过使用?.操作符取代.操作符,JavaScript 会在尝试访问obj.first.second 之前,先隐式地检查并确定obj.first 既不是null 也不是undefined。如果obj.firstnull或者undefined,表达式将会短路计算直接返回undefined

等价于以下表达式,但实际上没有创建临时变量:

let temp= obj.first;let nestedProp=((temp===null|| temp=== undefined)? undefined: temp.second);

可选链与函数使用

let result= someInterface.customMethod?.();

函数使用可选链操作符场景:

functiondoSomething(onContent, onError){try{// ... do something with the data}catch(err){
    onError?.(err.message);// 如果onError是undefined也不会有异常}}

可选链与表达式

当使用方括号与属性名的形式来访问属性时,你也可以使用可选链操作符:

let nestedProp= obj?.['prop'+'Name'];

可选链能用于赋值:

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

可选链访问数组

let arrayItem= arr?.[42];

空值合并运算符(Nullish coalescing Operator)

空值合并操作符(??)是一个逻辑操作符,当左侧的操作数为null 或者undefined时,返回其右侧操作数,否则返回左侧操作数。

与逻辑或操作符(||)不同,逻辑或操作符会在左侧操作数为假值时返回右侧操作数。也就是说,如果使用 || 来为某些变量设置默认值,可能会遇到意料之外的行为。比如为假值(例如,’’ 或 0)时。见下面的例子。

const foo=null??'default string';
console.log(foo);// "default string"const baz=0??42;
console.log(baz);// 0

使用空值合并操作符

console.log(null??"defaultValue1")// "defaultValue1"
console.log(undefined??"defaultValue2")// "defaultValue2"
console.log(""??"defaultValue3")// ""
console.log(0??"defaultValue4")// 0
console.log(40??"defaultValue5")// 40

为变量赋默认值
以前,如果想为一个变量赋默认值,通常的做法是使用逻辑或操作符(||):

let foo;//  foo is never assigned any value so it is still undefinedlet someDummyText= foo||'Hello!';

然而,由于||是一个布尔逻辑运算符,左侧的操作数会被强制转换成布尔值用于求值。任何假值(0''NaNnullundefined)都不会被返回。这导致如果你使用0''NaN作为有效值,就会出现不可预料的后果。

let count=0;let text="";let qty= count||42;let message= text||"hi!";
console.log(qty);// 42,而不是 0
console.log(message);// "hi!",而不是 ""

空值合并操作符可以避免这种陷阱,其只在第一个操作数为nullundefined时(而不是其它假值)返回第二个操作数:

let myText='';let notFalsyText= myText||'Hello world';
console.log(notFalsyText);// Hello worldlet preservingFalsy= myText??'Hi neighborhood';
console.log(preservingFalsy);// ''

短路
ORAND 逻辑操作符相似,当左表达式不为nullundefined 时,不会对右表达式进行求值。

functionA(){ console.log('函数 A 被调用了');return undefined;}functionB(){ console.log('函数 B 被调用了');returnfalse;}functionC(){ console.log('函数 C 被调用了');return"foo";}

console.log(A()??C());// 依次打印 "函数 A 被调用了"、"函数 C 被调用了"、"foo"// A() 返回了 undefined,所以操作符两边的表达式都被执行了

console.log(B()??C());// 依次打印 "函数 B 被调用了"、"false"// B() 返回了 false(既不是 null 也不是 undefined)// 所以右侧表达式没有被执行

不能直接与AND或OR操作符共用

null|| undefined??"foo";// 抛出 SyntaxErrortrue|| undefined??"foo";// 抛出 SyntaxError

但是加了括号来表明运算优先级,没有问题:

(null|| undefined)??"foo";// 返回 "foo"

与可选链操作符(?.)的关系

let customer={
  name:"Carl",
  details:{ age:82}};let customerCity= customer?.city??"暗之城";
console.log(customerCity);// “暗之城”
  • 作者:优小U
  • 原文链接:https://blog.csdn.net/zy1281539626/article/details/116735257
    更新时间:2022-07-18 14:17:31