JavaScript中if(id != null)与if(!id)判断逻辑的差异
这两种写法完全不等价,二者的判定规则差异极大,甚至大部分业务场景下的执行逻辑是完全相反的,你之前对==与null的比较规则也存在认知误区。
先纠正一个常见的认知偏差:
当
==/!=运算符的操作数中包含null或undefined时,不会触发任何跨类型的隐式转换。只有另一侧的值严格等于null或undefined时,比较结果才为true。
也就是说:
0 == null结果为false'' == null结果为false- 只有
null == null、undefined == null的结果为true
这也是id != null成为前端通用判定写法的核心原因——它刚好能同时筛掉未赋值的undefined和被显式置空的null,不会把0、空字符串这类带业务含义的有效值误判为无效。
第一种写法:if (id != null) {}
这个条件的触发规则非常简单:只要id既不是null,也不是undefined,条件就为真,会执行if块的代码。
哪怕id是0、空字符串''、布尔值false、NaN这类本身属于falsy的值,只要它的类型不是null/undefined,就会满足条件进入if块。
第二种写法:if (!id) {}
这个条件的触发规则是:先把id强制转换为布尔值,再对结果取反,只要id属于JS定义的falsy值集合,条件就为真,会执行if块的代码。
JS中完整的falsy值集合包括:
0- 空字符串
'' nullundefinedNaN- 布尔值
false
除此之外的所有值(包括非0数字、非空字符串、布尔值true、空数组、普通对象等),都会被判定为不满足这个条件,不会进入if块。
举几个常见的业务取值,直接对比两个写法的判定结果:
- 当
id = 123(合法的数字类用户ID):id != null判定为真,进入第一个写法的if块!id判定为假,不进入第二个写法的if块
- 当
id = 'order_456'(合法的字符串类订单ID):id != null判定为真,进入第一个写法的if块!id判定为假,不进入第二个写法的if块
- 当
id = [](空数组):id != null判定为真,进入第一个写法的if块!id判定为假(空数组转布尔值为真),不进入第二个写法的if块
- 当
id = 0(合法的枚举值ID):id != null判定为真,进入第一个写法的if块!id判定为真,也进入第二个写法的if块(这时候结果偶然重叠)
从对比就能看出来,只有当id是null、undefined、0、空字符串这类falsy值时,两个写法的结果才会偶然重叠;只要id是正常的业务有效值,两个写法的执行逻辑就会完全相反。如果误用!id的写法做存在性判定,会把0、空字符串这类合法业务值直接误判为无效,触发难以排查的线上bug。
内容的提问来源于stack exchange,提问作者LuJaks

