JavaScript运算符||、&&、空值合并、?.的区别和用法

文章目录

  • `||`和`&&`运算符
  • ??空值合并运算符
  • ?. 可选链
  • 总结

||&&是JS一直就有的运算符,虽然是逻辑运算符,但是我们经常拿来用于取值和赋值操作。而 ???.运算符是ES6加进来的, ??叫做“空值合并运算符”, ?.叫做“链式运算符”,接下来我们逐一介绍。

||&&运算符

一个是逻辑“或”,一个是逻辑“与”。你可不要被它的名字蒙蔽了,它们虽然叫逻辑运算符,但是他们跟C和Java这些强类型语言的逻辑运算符可不同,它们最显著的区别是:

JS逻辑运算符的操作数和返回值都可以不是布尔值

这是因为JS有些值虽然不是boolean类型,但是它们都可以当做“真值”和“假值”,我们常见的假值有falsenullundefined''0NaN,而其他的都可以作为真值。

我们用真值和假值来解释||&&的作用:

  • a || ba为真值则返回a,否则返回b
  • a && ba为假值则返回b,否则返回a

这是只有两个操作数的情况,如果操作数很多,比如a || b || c,我们可以这么来解释:

  • ||返回第一个真值,如果没有则返回最后一个值
  • &&返回第一个假值,如果没有则返回最后一个值

我们往往借助||在几个值中寻找一个真值,至于真值是哪一个值可能不重要,比如:

let val = val1 || val2 || val3; 

但是由于val1~3,可能都是假值,所以val最终可能也是个假值,所以我们在使用val的时候仍需非空判断:

let val = val1 || val2 || val3; 
if (val) {
	// todo
}

另外,||在取真值的时候还可以定义优先级,比如val1 || val2 || val3,它们的优先级为val1 > val2 > val3,即使三个数都为真,因为“短路效应”,也只返回第一个真值。这个特性有个普遍的应用场景:默认值。

function query(offset, limit) {
	offset = offset || 1;
	limit = limit || 10;
	// todo
}

我们把默认值放到||表达式的最后,用来“兜底”,这个在日常开发中屡见不鲜。

说完了||,我们再说&&

&&运算符遇到假值结束并返回假值,或者返回最后一个值。但是通常情况下,假值是没有意义的,所以我们通常的做法是想返回最后一个值,这里也有一个非常普遍的场景:链式调用。

let street = user && user.address && user.address.street;

现在是不是对||&&有了全新的认识。

??空值合并运算符

??之前,我们回顾一下||||是取真值,而0''falseNaN都是假值,都会被||无情“抛弃”。

但是这几个值它们都是“有值”,“有值”跟nullundefined还是有区别的。有些时候我们需要把它们当成“有意义”的值看待,比如0作为金额就是有意义的值,这个时候||运算符就无能为力了。

如果你不嫌麻烦,当然可以使用三元运算符:

function hasVal(val) {
	return val !== null && val !== undefined;
}
let val = hasVal(va1) ? va1 : (hasVal(val2) ? va2 : val3);

我嫌麻烦,所以我选择话????||的区别就是:||取真值,而??取有值。

a ?? b的含义是如果a不为nullundefined则返回a,否则返回b

举个例子:

let val1 = 0;
let val2 = 'hello';
val1 || val2; //  返回'hello',因为0为假值
val2 ?? val2; // 返回0,因为0为“有值” 

所以??弥补了||不能返回0false''NaN这几个“有值”的缺点。

?. 可选链

第一次见到?.这个运算符,还是在某乎上看讨论kotlin和java哪个好的文章,知道了kotlin有?.这个符号来避免NPE,没想到ES6中也引入了这个特性。

在讲?.之前,我们再次回顾一下之前的链式调用:

let street = user && user.address && user.address.street;

上面的情况,“链条”还不是很长,使用&&还能接受,如果我们把链条拉长,像下面这样:

let street = user && user.address 
                  && user.address.region;
                  && user.address.region.district
                  && user.address.region.district.street;

我还刻意格式化了一下代码,如果不格式化,可想多么痛苦。

这个时候我们就可以使用?.来优化了,这个运算符很好理解,我们知道user.address.是用来调用属性的,而?.表示若.前面有值(不为nullundefined)才调用,没有值返回undefined

改写之后的代码:

let street = user?.address?.region?.district?.street;

真是简洁且优雅。

总结

JavaScript运算符||、&&、空值合并、?.的区别和用法_第1张图片

最后,码字不易,还望评论支持。

你可能感兴趣的:(重拾JavaScript,javascript,kotlin,node.js)