官网定义:
可选链操作符( ?.
)允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。?.
操作符的功能类似于 .
链式操作符,不同之处在于,在引用为空(nullish ) (null 或者 undefined) 的情况下不会引起错误,该表达式短路返回值是 undefined
。与函数调用一起使用时,如果给定的函数不存在,则返回 undefined
。
优点:当尝试访问可能不存在的对象属性时,可选链操作符将会使表达式更短、更简明。在探索一个对象的内容时,如果不能确定哪些属性必定存在,可选链操作符也是很有帮助的
我的理解就是简化的三元判断,首先隐式的判断?前的变量是否存在,( 既不是 null
也不是 undefined
。)如果是null或者undefind 表达式将会短路计算直接返回 undefined
。
// 正常写法:为了避免报错,在访问obj.first.second之前,要保证 obj.first 的值既不是 null,
//也不是 //undefined。如果只是直接访问 obj.first.second,而不对 obj.first 进行校验,则有可能抛出
//错误。
let nestedProp = obj.first && obj.first.second;
//可选链操作符
//通过使用 ?. 操作符取代 . 操作符,JavaScript 会在尝试访问 obj.first.second 之前,先隐式地检查并
//确定 obj.first 既不是 null 也不是 undefined。如果obj.first 是 null 或者 undefined,表达式将会
//短路计算直接返回 undefined。
let nestedProp = obj.first?.second
语法:
obj?.prop obj?.[expr] arr?.[index] func?.(args)
可选链与函数调用
当尝试调用一个可能不存在的方法时也可以使用可选链。函数调用时如果被调用的方法不存在,使用可选链可以使表达式自动返回undefined
而不是抛出一个异常。
注意:如果?前不是一个方法名而是一个属性名,?.()是会报错的
let result = someInterface.customMethod?.();
处理可选的回调函数或者事件处理器
例如 try...catch...
// 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 name = person?.['age'+'name']
可选链并不能用于赋值
let object = {};
object?.property = 1;
// Uncaught SyntaxError: Invalid left-hand side in assignment
可选链访问数组元素
let arrayItem = arr?.[42];
短路计算
当在表达式中使用可选链时,如果左操作数是 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?.();
空值合并操作符
空值合并操作符(??
)是一个逻辑操作符,当左侧的操作数为 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数。
const foo = null ?? 'default string';
console.log(foo);
// expected output: "default string"
const baz = 0 ?? 42;
console.log(baz);
// expected output: 0
const nullValue = null;
const emptyText = ""; // 空字符串,是一个假值,Boolean("") === false
const 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
与或运算符的区别:
// “||”
let count = 0;
let text = "";
let qty = count || 42;
let message = text || "hi!";
console.log(qty); // 42,而不是 0
console.log(message); // "hi!",而不是 ""
// “ ?? ” 只有??左边为null 或 undefind时,才会执行??右边的值
let count = 0;
let text = "";
let qty = count ?? 42;
let message = text ?? "hi!";
console.log(qty); // 0
console.log(message); // ""
短路:
function A() { console.log('函数 A 被调用了'); return undefined; }
function B() { console.log('函数 B 被调用了'); return false; }
function C() { 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"; // 抛出 SyntaxError
true || undefined ?? "foo"; // 抛出 SyntaxError
空值合并操作符针对 undefined
与 null
这两个值,可选链式操作符(?.) 也是如此。