目录
踩坑描述:
最近在JS逻辑运算上踩了个坑,下面是我的代码:
const hasName = (user.name && user.name != "");
user的内容就是{name: ""}。
我的本意,是判断user的name属性不为空且值不为空,想得到一个boolean类型的结果,但是运行之后发现,hasName居然是个空字符串,就是user.name的值。这是怎么回事呢?
先把问题放一边,重新理解一下JS逻辑运算符的规则。
&& || !的规则:
之前写Java,逻辑运算符 && || 和!,都得使用boolean类型的值或者返回值是boolean类型的表达式进行运算,如下:
int a1 = true, b1 = false;
if (a1 && b1) {
// OK
}
int a2 = 0, b2 = false;
if (a2 && b2) {//编译不通过
}
但是Javascript不是,运算符可以对任意类型的数据做操作,在运算过程中会自动转换为boolean类型来进行运算。
具体规则如下:
1、String类型转化
非空字符串("abc")和空白字符串(" ")转换为true。空字符串("")转换为false。
2.Number类型转换
非0转换为true,0和NaN转换为false。
3.对象转换
任意对象包括空的对象({})转换为true。
数组包括空数组([])转换为true。
没有赋值或者赋值为空的对象转换为false,比如null对象。
4. Undefined转换为false
总结一下,转换为false的有"", 0, NaN, null, undefined.
知道了上面的规则,再来看我的bug:
踩坑问题分析
其实是这样,先计算&&左边,如果左边为false,则直接返回左边的结果,右边就不计算了。否则返回右边的结果,返回的时候不是转为boolean再返回。
看下面的例子可以加深理解:
"" && true 、true && "" 、"" && false 结果都是""。
0 && true、true && 0、0&&false 结果都是0。
1&& true结果是true,true && 1结果是1。
那么 false && ""、 false &&0结果是什么呢,结果是false,这个也好理解,&&左边是false,那么右边就不再计算了,直接返回左边的结果。
而或运算符||则是先计算左边,如果左边为true则直接返回左边的结果,否则返回右边的结果。
还有非!运算符,知道了任意类型转boolean的规则后,我那个bug就可以这么修改:
const hasName = !!user.name;//两个!!
如果user.name存在,且不为空,则hasName为true。