空值合并操作符 ?? 在 JavaScript 中用于精确处理默认值,仅当左侧为 null 或 undefined 时返回右侧值,与 || 运算符不同,后者会将 0、''、false 等假值也视为“空”。?? 更适用于 0、false、空字符串为有效值的场景,如配置项、用户输入等,能避免 || 带来的意外覆盖。使用时需注意:?? 不能与 && 或 || 混合使用而无括号,否则会报语法错误,必须通过括号明确优先级。该操作符自 ES2020 引入,现代浏览器支持良好,旧环境可通过 Babel 转译确保兼容。

JavaScript中的空值合并操作符
??
null
undefined
||
空值合并操作符
??
null
undefined
||
举个例子,假设我们有一个配置对象,其中某个属性可能未定义,或者明确设置为
null
// 传统方式,使用 ||
const configA = { timeout: 0 };
const timeoutA = configA.timeout || 3000; // timeoutA 会变成 3000,因为 0 是一个 falsy 值
const configB = { timeout: null };
const timeoutB = configB.timeout || 3000; // timeoutB 会变成 3000
const configC = {};
const timeoutC = configC.timeout || 3000; // timeoutC 会变成 3000
console.log(timeoutA); // 3000
console.log(timeoutB); // 3000
console.log(timeoutC); // 3000
// 使用 ??
const configD = { timeout: 0 };
const timeoutD = configD.timeout ?? 3000; // timeoutD 依然是 0,因为 0 既不是 null 也不是 undefined
const configE = { timeout: null };
const timeoutE = configE.timeout ?? 3000; // timeoutE 会变成 3000
const configF = {};
const timeoutF = configF.timeout ?? 3000; // timeoutF 会变成 3000,因为 configF.timeout 是 undefined
console.log(timeoutD); // 0
console.log(timeoutE); // 3000
console.log(timeoutF); // 3000从上面的例子可以看出,
??
0
''
false
||
null
undefined
??
||
这真的是一个非常值得深挖的问题,因为这两个运算符看起来相似,但在实际应用中,它们对“空”的定义完全不同。我个人觉得,理解这个区别是掌握
??
||
false
0
''
null
undefined
NaN
||
但是,问题也随之而来。设想一下,如果
0
''
false
timeout
0
userName
''
isAdmin
false
||
0
''
false
而
??
null
undefined
0
''
false
NaN
??
所以,本质区别在于:
||
??
null
undefined
理解这个差异,你就知道什么时候该用哪个了。
??
||
在实际开发中,我发现
??
??
当 0
false
''
??
timeout
0
const userSettings = {
timeout: 0,
retries: null
};
const actualTimeout = userSettings.timeout ?? 5000; // 得到 0,而不是 5000
const actualRetries = userSettings.retries ?? 3; // 得到 3
console.log(`Timeout: ${actualTimeout}, Retries: ${actualRetries}`); // Timeout: 0, Retries: 3isEnabled
false
false
true
const featureConfig = {
isEnabled: false,
// showTips: undefined
};
const displayFeature = featureConfig.isEnabled ?? true; // 得到 false
const showUserTips = featureConfig.showTips ?? true; // 得到 true
console.log(`Display Feature: ${displayFeature}, Show Tips: ${showUserTips}`); // Display Feature: false, Show Tips: trueconst userData = {
username: '',
email: null
};
const displayUsername = userData.username ?? '匿名用户'; // 得到 ''
const displayEmail = userData.email ?? '未提供'; // 得到 '未提供'
console.log(`Username: "${displayUsername}", Email: "${displayEmail}"`); // Username: "", Email: "未提供"维护数据类型和精确性: 当你从后端API获取数据时,如果某个字段可能返回
null
undefined
0
false
??
||
避免意外的副作用: 有时候,左侧表达式可能是一个函数调用,如果这个函数返回
0
false
??
总而言之,只要你认为
0
false
''
??
??
&&
||
是的,
??
&&
||
JavaScript为了避免操作符优先级可能导致的歧义,不允许 ??
&&
||
SyntaxError
比如,这样的写法是会报错的:
// 这会抛出 SyntaxError // const result = someValue ?? anotherValue || defaultValue; // const result = someValue ?? anotherValue && defaultValue;
这是因为
??
&&
||
正确的使用方式是使用括号来明确操作符的执行顺序:
结合 ||
||
??
const userPref = null; const defaultSetting = 'default'; const finalValue = (userPref || 'fallback') ?? defaultSetting; // 解释:userPref || 'fallback' -> null || 'fallback' -> 'fallback' // 'fallback' ?? defaultSetting -> 'fallback' console.log(finalValue); // 'fallback' const anotherPref = 0; const finalValue2 = (anotherPref || 'fallback') ?? defaultSetting; // 解释:anotherPref || 'fallback' -> 0 || 'fallback' -> 'fallback' // 'fallback' ?? defaultSetting -> 'fallback' console.log(finalValue2); // 'fallback'
如果你想先用
??
||
const userPrefA = undefined; const userPrefB = null; const userPrefC = 0; const result = (userPrefA ?? userPrefB) || userPrefC; // 解释:userPrefA ?? userPrefB -> undefined ?? null -> null // null || userPrefC -> null || 0 -> 0 console.log(result); // 0
结合 &&
&&
??
const condition = true; const value = null; const finalResult = (condition && value) ?? 'default'; // 解释:condition && value -> true && null -> null // null ?? 'default' -> 'default' console.log(finalResult); // 'default' const condition2 = false; const value2 = 'data'; const finalResult2 = (condition2 && value2) ?? 'default'; // 解释:condition2 && value2 -> false && 'data' -> false // false ?? 'default' -> false console.log(finalResult2); // false
如果你想先用
??
&&
const a = undefined; const b = 'hello'; const c = 'world'; const result = (a ?? b) && c; // 解释:a ?? b -> undefined ?? 'hello' -> 'hello' // 'hello' && c -> 'hello' && 'world' -> 'world' console.log(result); // 'world'
总结注意事项:
??
&&
||
??
&&
||
??
??
??
浏览器兼容性: 目前,主流的现代浏览器对
??
你可以访问像 caniuse.com 这样的网站来查看最新的兼容性信息。对于绝大多数桌面和移动端用户来说,现在使用
??
Polyfill 方案: 虽然现代浏览器支持良好,但如果你需要支持一些老旧的浏览器环境(例如,一些企业内部应用可能还在使用旧版IE,或者某些嵌入式浏览器),那么你就需要考虑 Polyfill 或转译(Transpilation)方案。
通常,我们不会直接为
??
当你使用 Babel 时,配合
@babel/preset-env
??
例如,
a ?? b
var a = someValue; var b = defaultValue; var result = (a !== null && a !== undefined) ? a : b;
或者更简洁的:
var result = (someValue == null) ? defaultValue : someValue;
(注意这里的
== null
null
undefined
如何配置 Babel: 如果你正在使用 Webpack、Rollup 或 Parcel 等构建工具,你通常会在 Babel 的配置文件(如
.babelrc
babel.config.js
@babel/preset-env
一个简单的
babel.config.js
module.exports = {
presets: [
[
'@babel/preset-env',
{
targets: {
edge: '17',
firefox: '60',
chrome: '67',
safari: '11.1',
// 你可以根据你的项目需求指定支持的浏览器版本
},
useBuiltIns: 'usage', // 如果需要,也可以配置polyfill
corejs: 3,
},
],
],
};通过这样的配置,Babel 会自动处理
??
在我看来,对于大多数现代前端项目,直接使用
??
以上就是什么是JS的空值合并操作?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号