Javascript 可选链

74 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第11天,点击查看活动详情 Johnny

对于javaScript开发者都会遇到一个问题:访问一个可选的子属性需要额外的逻辑来测试它是否存在。

例如,我们有一个article对象,其包含一个名为relatedArticle的对象属性,这个字段主要是用来保存相关文章的一些信息,假设我们通过以下方式访问相关文章的 URL

article.relatedArticle.url

然而,并非每篇文章都有相关文章,这种情况下则会报错:


Cannot read properties of undefined (reading 'url')

所以说我们先需要判断相关文章是否存在!

let article = {};
let url;
if(article.relatedArticle !== undefined) {
    url = article.relatedArticle.url;
}

或者我们可能会想尝试这样的写法:

let article = {}
let url = article.relatedArticle ? article.relatedArticle : undefined;

但是,如果我们有多个子级别,我们最终可能会编写很长的undefined语句串。例如,下面我们article.relatedArticle.url.rootDomain在不确定这些对象是否会被定义时尝试访问:

let article = {};
let rootDomain;
if(article.relatedArticle !== undefined && article.relatedArticle.url !== undefined) {
    rootDomain = article.relatedArticle.url.rootDomain;
}

可选链解决了过多逻辑检查的问题,如果某个东西被赋予了一个可选?.标签,那么如果它存在,则该值将被返回——否则它不会抛出错误。在上面的例子中,我们甚至不再需要一个if语句了:

let article = {};
let rootDomain = article.relatedArticle?.url?.rootDomain;

如何在 Javascript 中使用可选链

在大多数示例中,可以使用如上所述的可选链,以避免对象中可选的属性出现错误:

let article = {};
let rootDomain = article.relatedArticle?.url?.rootDomain;

需要注意的是,我们不能在对象的末尾添加?

let article = {};
let rootDomain = article.relatedArticle?.url?.rootDomain?;
// Will throw an error like `Unexpected token ';'`

可选链在函数中的应用

可以将可选链接与您期望可能返回对象的函数一起使用。它的工作方式与之前完全相同,只是我们?.在函数之后添加 - myFunction(...arguments)?.x:

let myFunction = (x, y, z) => {
    if(z !== undefined) {
        return {
            x: x,
            y: y,
            z: z
        }
    }
}

let arguments = [ 1, 2, 3 ];

let getX = myFunction(...arguments)?.x;
console.log(getX); // Returns 1;

默认情况下,如果一个函数没有return,它会返回undefined——所以这在你不确定一个函数是否会返回任何东西的情况下非常有用。

可选链在数组中的应用

可选链接也可以与数组一起使用。例如 - 如果你不确定对象中是否存在一个数组属性。下面,用户可以拥有一组有效地址,我们希望从他们的第一个地址获取他们地址的第一行。由于它可能并不总是存在,我们可以在这里使用可选链接来尝试访问它。

let myUser = {
    name: "John Doe",
    age: 155
}

let getAddress = myUser.addresses?.[0]?.first

总结

可选链非常有用,并且得到广泛支持(不包括 Internet Explorer)。它几乎可以与属性、数组或函数的任意组合一起使用,具体取决于返回类型。例如:

obj?.property obj?.[property] obj[index]?.property obj?.(args) func(args)?.property