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