??只在null或undefined时取默认值,保留0、''、false等合法值;||对所有falsy值(含0、''、false、null、undefined、nan)均触发默认值,易误覆盖有效输入。

JS 中可以用短路运算符(|| 或 ??)为函数参数提供默认值,但要注意它们的适用场景和行为差异——|| 会把所有“falsy”值(如 0、''、false、null、undefined、NaN)都当作“未传值”,而 ??(空值合并运算符)只在值为 null 或 undefined 时才使用默认值,更安全、更符合“默认参数”的本意。
用 ?? 设置真正意义上的默认参数
这是推荐方式,尤其当你希望保留 0、false、空字符串等合法值时:
function greet(name) {
const realName = name ?? 'Anonymous';
return `Hello, ${realName}!`;
}
greet('Alice'); // "Hello, Alice!"
greet(''); // "Hello, !"
greet(0); // "Hello, 0!"
greet(null); // "Hello, Anonymous!"
greet(undefined); // "Hello, Anonymous!"
避免误用 || 导致逻辑错误
|| 在遇到任何 falsy 值都会触发默认值,容易掩盖有效输入:
function count(items) {
return items || 10; // ❌ 错误:传入 [] 或 0 也会返回 10
}
count([1, 2]); // [1, 2] ✅
count([]); // 10 ❌(空数组是合法输入,不应被覆盖)
count(0); // 10 ❌(0 可能是有效计数)
如果真要用 ||,务必确认你**确实想忽略所有 falsy 值**,比如只用于兜底“完全没传参”的情况(且不关心具体 falsy 值)。
与 ES6 默认参数结合使用更清晰
现代写法优先用函数参数自带的默认值语法,它语义明确、支持解构、且只在 undefined 时生效(类似 ??):
function fetchUser(id = 'default-id', options = {}) {
// id 未传或显式传 undefined → 用 'default-id'
// options 未传 → 用 {}
}
短路运算符更适合在函数体内对**已接收的参数或中间变量**做兜底处理,例如:
- 对解构后的属性设默认值:
const { timeout = 5000 } = options ?? {}; - 链式取值防报错:
user?.profile?.name ?? 'No name' - 兼容老环境(无默认参数语法)时的降级写法
小结:选哪个?
- 想严格区分“没传”和“传了 falsy 值” → 用
??或 ES6 默认参数 - 需要兼容 IE 或极旧环境 → 可用
||,但必须检查是否允许丢弃0/false/'' - 处理对象嵌套属性或可选链结果 →
??是首选











