摘要: 在本教程中,您将了解可选链运算符 (?.
),它简化了通过连接对象访问值的方式。
JavaScript 可选链运算符简介
可选链运算符 (?.
) 就像一个访问对象系列中嵌套属性的快捷方式。 您无需检查链中每个步骤是否为空 (null
或 undefined
),而是可以使用运算符 ?.
直接访问所需的属性。
如果链的任何部分为空,可选链运算符 (?.
) 将立即停止并返回 undefined
作为结果。 它可以避免您为链中每个步骤编写额外的检查。
假设您有一个返回 user
对象的函数
function getUser(id) {
if(id <= 0) {
return null;
}
// get the user from database
// and return null if id does not exist
// ...
// if user was found, return the user
return {
id: id,
username: 'admin',
profile: {
avatar: '/avatar.png',
language: 'English'
}
}
}
Code language: JavaScript (javascript)
以下示例使用 getUser()
函数访问用户资料
let user = getUser(1);
let profile = user.profile;
Code language: JavaScript (javascript)
但是,如果您传递的 id
小于或等于零,或者 id
在数据库中不存在,getUser()
函数将返回 null
。
因此,在访问 avatar
属性之前,您需要使用 逻辑运算符 AND 检查 user
是否不为 null
let user = getUser(2);
let profile = user && user.profile;
Code language: JavaScript (javascript)
在此示例中,我们确认 user
不为 null
或 undefined
,然后才访问 user.profile
属性的值。 它可以防止在未首先检查用户的情况下直接访问 user.profile
时出现的错误。
ES2020 引入了可选链运算符,它由问号后跟一个点表示
?.
Code language: JavaScript (javascript)
要使用可选链运算符访问对象的属性,请使用以下方法之一
objectName ?. propertyName
objectName ?. [expression]
Code language: JavaScript (javascript)
可选链运算符隐式地检查 user
是否不为 null
或 undefined
,然后才尝试访问 user.profile
let user = getUser(2);
let profile = user ?. profile;
Code language: JavaScript (javascript)
在此示例中,如果 user
为 null
或 undefined
,可选链运算符 (?.
) 将立即返回 undefined
。
从技术上讲,它等效于以下内容
let user = getUser(2);
let profile = (user !== null || user !== undefined)
? user.profile
: undefined;
Code language: JavaScript (javascript)
堆叠可选链运算符
如果 getUser()
返回的 user
对象没有 profile
属性,则在没有先检查 user.profile
的情况下尝试访问 avatar
将导致错误。
为了避免错误,您可以多次使用可选链运算符,如下所示
let user = getUser(-1);
let avatar = user ?. profile ?. avatar;
Code language: JavaScript (javascript)
在这种情况下,avatar
为 undefined
。
与空值合并运算符结合使用
如果您想为 user
指定默认资料,可以将可选链运算符 (?.
) 与空值合并运算符 (??
) 结合使用,如下所示
let defaultProfile = { default: '/default.png', language: 'English'};
let user = getUser(2);
let profile = user ?. profile ?? defaultProfile;
Code language: JavaScript (javascript)
在此示例中,如果 user.profile
为 null
或 undefined
,由于空值合并运算符的存在,资料将采用 defaultProfile
将可选链运算符与函数调用结合使用
假设您有一个文件 API,如下所示
let file = {
read() {
return 'file content';
},
write(content) {
console.log(`Writing ${content} to file...`);
return true;
}
};
Code language: JavaScript (javascript)
此示例调用 file
对象的 read()
方法
let data = file.read();
console.log(data);
Code language: JavaScript (javascript)
如果您调用 file
对象中不存在的方法,您将收到 TypeError
let compressedData = file.compress();
Code language: JavaScript (javascript)
错误
Uncaught TypeError: file.compress is not a function
Code language: JavaScript (javascript)
但是,如果您将可选链运算符与方法调用一起使用,表达式将返回 undefined
而不是抛出错误
let compressedData = file.compress?.();
Code language: JavaScript (javascript)
现在 compressedData
为 undefined
。
这在您使用 API 时很有用,在该 API 中,方法可能由于某种原因不可用,例如特定浏览器或设备。
以下示例说明了将可选链运算符与函数或方法调用一起使用的语法
functionName ?. (args)
Code language: JavaScript (javascript)
可选链运算符 (?.
) 在您有一个带可选 回调 的函数时也很有用
function getUser(id, callback) {
// get user
// ...
let user = {
id: id,
username: 'admin'
};
// test if the callback exists
if ( callback ) {
callback(user);
}
return user;
}
Code language: JavaScript (javascript)
通过使用可选链运算符,您可以跳过回调是否存在时的测试
function getUser(id, callback) {
// get user
// ...
let user = {
id: id,
username: 'admin'
};
// test if the callback exists
callback ?. (user);
return user;
}
Code language: JavaScript (javascript)
总结
- 可选链运算符 (
?.
) 在您尝试访问null
或undefined
对象的属性时返回undefined
,而不是抛出错误:obj ?. property
。 - 将可选链运算符 (
?.
) 与空值合并运算符 (??
) 结合使用,以指定默认值。 - 使用
functionName ?. (args)
避免在调用functionName
之前显式检查它是否不为undefined
或null
。