最近又遇到空值匹配的问题, 在编写javascript
代码时, 尤其是需要和后端同学配合的时候, 空值处理不好是非常容易出问题的, 趁此机会彻底搞清楚吧.
1. 准备工作: 使用脚本生成各种边界值的 ==
和 ===
比较结果, 这份结果基本涵盖了js中能遇到的所有常见或常用的数据类型和结构.
2. 比较结果:
== | 0 | 1 | -0 | NaN | "" | foo | {} | { f: "b" } | [] | ["foo"] | true | false | null | undefined | Infinity | -Infinity |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | true | |||||||||||||||
1 | false | true | ||||||||||||||
-0 | true | false | true | |||||||||||||
NaN | false | false | false | false | ||||||||||||
"" | true | false | true | false | true | |||||||||||
foo | false | false | false | false | false | true | ||||||||||
{} | false | false | false | false | false | false | true | |||||||||
{ f: "b" } | false | false | false | false | false | false | false | true | ||||||||
[] | true | false | true | false | true | false | false | false | true | |||||||
["foo"] | false | false | false | false | false | true | false | false | false | true | ||||||
true | false | true | false | false | false | false | false | false | false | false | true | |||||
false | true | false | true | false | true | false | false | false | true | false | false | true | ||||
null | false | false | false | false | false | false | false | false | false | false | false | false | true | |||
undefined | false | false | false | false | false | false | false | false | false | false | false | false | true | true | ||
Infinity | false | false | false | false | false | false | false | false | false | false | false | false | false | false | true | |
-Infinity | false | false | false | false | false | false | false | false | false | false | false | false | false | false | false | true |
=== | 0 | 1 | -0 | NaN | "" | foo | {} | { f: "b" } | [] | ["foo"] | true | false | null | undefined | Infinity | -Infinity |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | true | |||||||||||||||
1 | false | true | ||||||||||||||
-0 | true | false | true | |||||||||||||
NaN | false | false | false | false | ||||||||||||
"" | false | false | false | false | true | |||||||||||
foo | false | false | false | false | false | true | ||||||||||
{} | false | false | false | false | false | false | true | |||||||||
{ f: "b" } | false | false | false | false | false | false | false | true | ||||||||
[] | false | false | false | false | false | false | false | false | true | |||||||
["foo"] | false | false | false | false | false | false | false | false | false | true | ||||||
true | false | false | false | false | false | false | false | false | false | false | true | |||||
false | false | false | false | false | false | false | false | false | false | false | false | true | ||||
null | false | false | false | false | false | false | false | false | false | false | false | false | true | |||
undefined | false | false | false | false | false | false | false | false | false | false | false | false | false | true | ||
Infinity | false | false | false | false | false | false | false | false | false | false | false | false | false | false | true | |
-Infinity | false | false | false | false | false | false | false | false | false | false | false | false | false | false | false | true |
3. 不同之处
我把 ===
的比较结果中与==
不同的部分, 使用红色方框标出.
4. 结论
- 在两张表的对角线上都是自己与自己比较, 除
NaN
这朵奇葩之外, 其他所有值都与自身相等. 这是因为IEEE 754 就是这么规定的. -
0
,+0
,-0
等价, (使用Object.is
可以区分); -
Infinity
-Infinity
都只和自身相等===
, 和其他任何类型任何值都不等; - 不同部分(红色框内容)都是
===
的结果是false
而==
结果是true
, 这是因为==
操作包含隐式转换,===
操作则不包含, 隐式转换是指:
相等操作符比较两个值是否相等,在比较前将两个被比较的值转换为相同类型。在转换后(等式的一边或两边都可能被转换),最终的比较方式等同于全等操作符 === 的比较方式。 相等操作符满足交换律。
转换规则:
undefined
和null
互相相等, 但是与其他四种类型(Number
,String
,Boolean
,Object
)不等;
Number
与其他类型比较时, 其他类型ToNumber
|ToPrimitive
;
Object
与其他类型比较时, 自身ToPrimitive
;
String
与Boolean
比较时, 双方ToNumber
;
-
[]
空数组, 会被隐式转换为false
或者0
, 而空对象不会; -
Object
类型互相比较时, 两种方式都是比较内存引用是否同一引用对象, 而不是比较其属性值或者ToPrimitive
, 示例中相等是因为引用的同一对象. -
javascript
中还有"同值相等", "零值相等",Object.is
的比较方法, 具体可参考文末链接.
5. 建议
1 编写与 RESTful API 交互应用时应与编写 API 的同学约定好数据交换协议, 比如属性为空时如何体现:
// 任然返回该属性, 以null || ''表示
{
name: 'Jack',
hobbies: null,
alias: ''
}
// 不包含该属性
{
name: 'Jack'
}
两种方式各有优劣, 只是后续处理时略有不同, 如果事先没有考虑这方面的情况, 那么未知情况可能随时发生, 页面上有可能会出现 undefined 或者 null 之类的文字.
2 数组处理尤为重要, 同上一条, 为空时的数组究竟是不返回, 还是返回null
, 或者返回空数组 []
? 每个人都有自己的看法, 但是前端同学需要自己处理好各种情况的返回 避免被坑.
参考:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators