zl程序教程

您现在的位置是:首页 >  Java

当前栏目

可选链运算符(?.)

2023-02-18 16:29:05 时间

bug收集:专门解决与收集bug的网站

网址:www.bugshouji.com

今天给大家分享可选链运算符(?.)

背景:

在 ES2020 之前,如果要访问 JavaScript 中对象的嵌套属性,则必须在每个级别检查是否为 null 或 undefined,否则最终将会抛出 TypeError。

为了避免出现 TypeError,我们将不得不创建临时变量或执行一系列增量 && 调用,这看起来很丑陋,并且同时占用了空间和时间。

例如:

const obj = {
  prop: {
    a: "value"
 }
}

// before ES2020 - no checks
obj.foo.a  // TypeError: Cannot read property 'a' of undefined

// before ES2020 - incremental nested checks
obj.foo && obj.foo.b   // undefined

在ES2020中,通过可选链运算符 ?. ,现在我们就可以内联进行这些检查了。

官方定义:

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

语法:

obj.val?.prop
obj.val?.[expr]
obj.func?.(args)

描述

可选链与对象的引用

可选链运算符之前,对象引用是为了避免出错,使用用&&来验证

let nestedProp = obj.first && obj.first.second;

有了可选链运算符(?.),在访问 obj.first.second 之前,不再需要明确地校验 obj.first 的状态,再并用短路计算获取最终结果:

let nestedProp = obj.first?.second;

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

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

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

可选链与函数调用

函数调用时如果被调用的方法不存在,使用可选链可以使表达式自动返回undefined而不是抛出一个异常。

let result = someInterface.customMethod?.();

注: 如果存在一个属性名且不是函数,使用 ?. 仍然会产生一个 TypeError 异常 (x.y is not a function).

处理可选的回调函数或者事件处理器

使用?.的你可以忽略这些额外的校验

//  ES2019 的写法
function doSomething(onContent, onError) {
try {
// ... do something with the data
  }
catch (err) {
if (onError) { // 校验 onError 是否真的存在
      onError(err.message);
    }
  }
}
// 使用可选链进行函数调用
function doSomething(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];

基本例子

如下的例子在一个不含 bar 成员的 Map 中查找 bar 成员的 name 属性,因此结果是 undefined。

let myMap = new Map();
myMap.set("foo", {name: "baz", desc: "inga"});


let nameBar = myMap.get("bar")?.name;

短路计算

当在表达式中使用可选链时,如果左操作数是 null 或 undefined,表达式将不会被计算,例如:

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


console.log(x); // x 将不会被递增,依旧输出 0

连用可选链运算符

可以连续使用可选链读取多层嵌套结构:

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: "Carl",
  details: { age: 82 }
};
let customerCity = customer?.city ?? "暗之城";
console.log(customerCity); // “暗之城”

苟有恒 , 何必三更眠五更起