记录:由运算符优先级导致的bug
错误代码以及问题现象
组件日期格式始终显示为 YYYY-MM-DD HH:mm:ss
,即使已显式传入 format
参数
<DatePicker format={format ?? showTime ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD'}
/>
原因分析
运算符优先级混淆
JavaScript 运算符优先级表(部分):
运算符 | 优先级 | 结合性 |
---|---|---|
?? (空值合并) | 5 | 从左到右 |
?: (三元运算) | 4 | 从右到左 |
实际执行逻辑:
// 等效于
(format ?? showTime) ? '...HH:mm:ss' : '...YYYY-MM-DD'
当 format
存在值时:
??
先执行返回非空值- 将非空值转换为布尔值进行三元运算
- 任何真值都会触发选择时间格式
解决方案
正确写法
// ✅ 正确使用括号明确优先级
<DatePickerformat={format ?? (showTime ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD')}
/>
执行逻辑分解
- 优先处理三元表达式:
const defaultFormat = showTime ? '...HH:mm:ss' : '...YYYY-MM-DD';
- 执行空值合并运算:
finalFormat = format ?? defaultFormat;
验证示例
测试用例 | 原代码结果 | 修正后结果 |
---|---|---|
format=“YYYY/MM/DD” | HH:mm:ss 格式 | YYYY/MM/DD |
format=null, showTime=true | HH:mm:ss 格式 | HH:mm:ss 格式 |
format=undefined, showTime=false | HH:mm:ss 格式 | YYYY-MM-DD |
最佳实践
- 括号优先原则:混合使用逻辑运算符时显式使用括号
- 分步处理:对复杂逻辑进行分解
const getDefaultFormat = () => showTime ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD';<DatePicker format={format ?? getDefaultFormat()} />
- 类型守卫:严格判断空值
const finalFormat = typeof format === 'string' ? format : defaultFormat;
关键点:当
??
与?:
混合使用时,永远显式使用括号明确优先级关系。