
JavaScript 可选链接运算符 ?.
在本教程中,您将了解可选的链接运算符 ?.,它简化已连接对象的访问值的方式
在本教程中,您将了解可选的链接运算符 ?.,它简化已连接对象的访问值的方式。
JavaScript 可选链运算符介绍
可选的链接运算符 ?. 允许您访问位于对象链深处的属性值,而无需显式检查链中的每个引用是否为null 或者是 undefined 。
如果链中的引用对象之一是 null 或者 undefined,则可选的链接运算符 ?. 将短路并返回 undefined。
假设您有一个返回 user 对象的函数:
function getUser(id) {
    if(id <= 0) {
        return null;
    }
    // 获取用户从数据库
    // 如果用户不存在则返回null
    // ...
    
    // 如果用户找到,则返回用户
    return {
        id: id,
        username: 'admin',
        profile: {
            avatar: '/avatar.png',
            language: 'English'
        }
    }
}然后使用 getUser() 函数访问用户配置文件:
let user = getUser(1);
let profile = user.profile;但是,如果您传递 id 小于或等于零或 id 在数据库不存在 ,getUser() 函数将返回 null。
因此,在访问 avatar 属性之前,您需要检查 user 是否是null,使用逻辑运算符:
let user = getUser(2);
let profile = user && user.profile;在此示例中,我们确认 user 不是 undefined 或 null 之前访问 user.profile 属性的值。它可以避免直接访问 user.profile 引发的错误。
ES2020 引入可选的链接运算符,由问号后跟一个点表示:
?.要使用可选的链接运算符访问对象的属性,您可以使用以下语法之一:
objectName ?. propertyName
objectName ?. [expression]可选的链接运算符在尝试访问 user.profile 之前,隐式检查 user 是否是 null 或 undefined:
let user = getUser(2);
let profile = user ?. profile;在此示例中,如果 user 是 null 或者 undefined,则可选的链接运算符 ?. 会立即返回 undefined。
从技术上讲,它等同于下面的语句:
let user = getUser(2);
let profile = (user !== null || user !== undefined)
            ? user.profile
            : undefined;堆叠可选的链接运算符
如果 getUser() 返回的 user 对象没有 profile 属性。在不检查第一个的情况下尝试访问 user.profile 的 avatar 属性将会导致错误。
为避免错误,您可以多次使用可选的链接运算符,如下所示:
let user = getUser(-1);
let avatar = user ?. profile ?. avatar;在这种情况下,avatar 是 undefined.
组合空值合并运算符
如果要将默认配置文件分配给 user,可以将可选的链接运算符 ?. 与空值合并运算符 ?? 组合使用,如下所示:
let defaultProfile =  { default: '/default.png', language: 'English'};
let user = getUser(2);
let profile = user ?. profile ?? defaultProfile;在此示例中,如果 user.profile 是 null 或者是 undefined,则配置文件将因为空值合并运算符而采用 defaultProfile:
在函数使用可选的链接运算符
假设您有一个文件 API,如下所示:
let file = {
    read() {
        return 'file content';
    },
    write(content) {
        console.log(`Writing ${content} to file...`);
        return true;
    }
};本例调用 file 对象的 read() 方法:
let data = file.read();
console.log(data);如果您调用 file 对象中不存在的方法,您将得到 TypeError:
let compressedData = file.compress();错误:
Uncaught TypeError: file.compress is not a function但是,如果您在方法调用中使用可选的链接运算符,表达式将返回 undefined 而不是抛出错误:
let compressedData = file.compress?.();compressedData 现在是 undefined。
当您使用的 API 中的方法可能由于某种原因(例如,特定的浏览器或设备)不可用时,这很有用。
下面展示在函数或方法调用中使用可选链接运算符的语法:
functionName ?. (args)如果您有一个带有可选回调的函数,则可选的链接运算符 ?. 也很有用:
function getUser(id, callback) {
    // 获取用户
    // ...
    let user = {
        id: id,
        username: 'admin'
    };
    // 判断回调是否存在
    if ( callback ) {
        callback(user);
    }
    return user;
}
通过使用可选的链接运算符,如果回调存在,您可以跳过判断:
function getUser(id, callback) {
    // 获取用户
    // ...
    let user = {
        id: id,
        username: 'admin'
    };
    // test if the callback exists
    callback ?. (user);
    return user;
}
结论
如果您尝试访问一个为 null 或者 undefined 的对象属性,可选的链接运算符 ?. 将返回 undefined 而不是抛出错误:。
将可选的链接运算符 ?. 与空值合并运算符 ?? 组合使用可以分配默认值。
functionName ?. (args) 用于在调用 functionName 之前,避免显式检查 functionName 是否存在undefined或null。
















