我无法确认此语法是否正确。
它是正确的 TypeScript 代码,并且是正确的 JavaScript,具体取决于您运行它的引擎。Chrome (V8) 已经支持这种语法(请参阅 caniuse.com)。
您可以在此处阅读更多关于 proposal to add this syntax 未来 JS 规范的信息。
这是什么?
这种语法称为可选链接运算符,它允许您访问对象上可能存在或不存在的属性而无需检查属性是否存在,无论多深属性访问表达式是。
例如,假设我们有这样的对象:
const user = {
details: {
name: "SpongeBob SquarePants"
},
repo: null
};
我们想得到他们的名字,如果存在的话,还有一些属性user.repo.url。我们可以使用可选的链接运算符来获取两者,而不必担心repo 是否是一个对象:
console.log(user.details.name) //=> "SpongeBob SquarePants"
console.log(user.repo.url) //=> undefined
它也适用于函数调用。例如,假设user.repo 有一个值,我们知道它将是一个返回字符串的函数。但是,有时,如上所述,它可能不是一个函数。如果函数存在,我们可以执行以下操作来调用该函数,但如果user.repo.url 处的值不是函数,则代码不会抛出错误:
console.log(user.repo?.url()) //=> undefined
没有可选的链接运算符?
您可以通过显式检查您正在访问的属性链中每个对象属性的真实性来实现与可选链接运算符类似的行为。
这可以通过利用 JavaScript 的 short-circuit evaluation 行为来完成,或者更明显的是使用 ternary operator。
看起来像这样:
function getItems_shortCircuit(obj) {
return obj && obj.widgets && obj.widgets.items
}
function getItems_ternary(obj) {
return obj
? obj.widgets
? obj.widgets.items
? obj.widgets.items
: null
: null
: null
}
let cart = {
widgets: null
}
console.log(getItems_shortCircuit(cart)) //=> null
cart.widgets = {
items: ["a", "b"]
}
console.log(getItems_ternary(cart)) //=> ["a", "b"]
我对上述代码的担忧是cart?.widgets?.items 是否会引发任何错误。
这取决于项目是否使用 TypeScript,它支持开箱即用的optional chaining (?.)。你可以在TypeScript documentation阅读它。
如果你不使用 TypeScript,那么你必须使用一些 ESNext 编译器来编译你的应用程序,比如 Babel,它有 @babel/plugin-proposal-optional-chaining plugin。