1、 ?? 空值合并操作符

在JavaScript中,??运算符被称为nullish coalescing运算符(零合并操作符)。
  空值合并操作符(??)是一个逻辑操作符,当左侧的操作数为 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数。
  与逻辑或操作符(||)不同,逻辑或操作符会在左侧操作数为假值时返回右侧操作数。也就是说,如果应用 || 来为某些变量设置默认值,可能会遇到意料之外的行为。比方为假值(例如,'' 或 0)时。见上面的例子。

const foo = null ?? 'default string';console.log(foo);    // 输入: "default string" const baz = 0 ?? 42;console.log(baz);    // 输入: 0
const nullValue = null;const emptyText = ""; // 空字符串,是一个假值,Boolean("") === falseconst someNumber = 42; const valA = nullValue ?? "valA 的默认值";const valB = emptyText ?? "valB 的默认值";const valC = someNumber ?? 0; console.log(valA); // "valA 的默认值"console.log(valB); // ""(空字符串尽管是假值,但不是 null 或者 undefined)console.log(valC); // 42

2、??= 空值赋值操作符

这个赋值操作符只有在以后值为空或未定义的状况下才会赋一个新的值。上面的例子强调了这个操作符实质上是空值赋值的语法糖。

var x = nullvar y = 5console.log( x ??= y )    // 输入: 5console.log( x = (x ?? y) )    // 输入: 5 

3、?. 可选链操作符

可选链操作符( ?. )容许读取位于连贯对象链深处的属性的值,而不用明确验证链中的每个援用是否无效。?. 操作符的性能相似于 . 链式操作符,不同之处在于,在援用为空(nullish ) (null 或者 undefined) 的状况下不会引起谬误,该表达式短路返回值。

语法:obj?.prop   obj?.[expr]   arr?.[index]    func?.(args)
const adventurer = {  name: 'Alice',  cat: {    name: 'Dinah'  }}; const dogName = adventurer.dog?.name;console.log(dogName);    // 输入: undefinedconsole.log(adventurer.someNonExistentMethod?.());    // 输入: undefined

函数调用:

let result = someInterface.customMethod?.();//如果心愿容许 someInterface 也为 null 或者 undefined ,那么你须要像这样写 someInterface?.customMethod?.()可选链与表达式: let nestedProp = obj?.['prop' + 'Name'];

可选链拜访数组:

let arrayItem = arr?.[42];例子:    let myMap = new Map();    myMap.set("foo", {name: "baz", desc: "inga"});     let nameBar = myMap.get("bar")?.name;    在一个不含 bar 成员的 Map 中查找 bar 成员的 name 属性,因而后果是 undefined。

连用可选链操作:

let customer = {  name: "Carl",  details: {    age: 82,    location: "Paradise Falls" // details 的 address 属性未有定义  }};let customerCity = customer.details?.address?.city;// … 可选链也能够和函数调用一起应用let duration = vacations.trip?.getTime?.();

空值合并操作符能够在应用可选链时设置一个默认值:

let customer = {  name: "open",  details: { age: 98 }}; let customerCity = customer?.city ?? "666";console.log(customerCity);  // 输入:666

应用这个运算符,有几个留神点:

(1)短路机制

a?.[++x]// 等同于a == null ? undefined : a[++x]

下面代码中,如果 a 是 undefined 或 null,那么 x 不会进行递增运算。也就是说,链判断运算符一旦为真,右侧的表达式就不再求值。
(2)括号的影响

(a?.b).c// 等价于(a == null ? undefined : a.b).c

下面代码中,?. 对圆括号内部没有影响,不论 a 对象是否存在,圆括号前面的 .c 总是会执行。
一般来说,应用 ?. 运算符的场合,不应该应用圆括号。
(3)右侧不得为十进制数值
为了保障兼容以前的代码,容许 foo ?. 3 : 0 被解析成 foo ? .3 : 0,因而规定如果 ?. 前面紧跟一个十进制数字,那么 ?. 不再被看成是一个残缺的运算符,而会依照三元运算符进行解决,也就是说,那个小数点会归属于前面的十进制数字,造成一个小数。