+! 运算符在if语句中
我正在审查一个angularjs工厂的代码,以更好地理解它是如何工作的。 代码包含一个if
语句,我不完全理解。
作者在一个plnkr演示中写道:
if ((+!!config.template) + (+!!config.templateUrl) !== 1) { throw new Error('Expected modal to have exactly one of either `template` or `templateUrl`'); }
它在github回购中略有不同:
if (!(!config.template ^ !config.templateUrl)) { throw new Error('Expected modal to have exactly one of either `template` or `templateUrl`'); }
显然通过错误消息它检查是否存在两个之一。 我只是不确定如何得出结论。 我一直没有find^
或+!
任何信息+!
我的问题是:这个if语句是如何工作的? ( ^
或+!
或者+!!
具体)
!!
将值转换为布尔值( true
或false
)。 +
然后将该布尔转换为一个数字, 1
为true
或0
为false。
> +true 1 > +false 0
就我个人而言,在处理两个布尔值时,我发现写更类似这样的东西:
if (!config.template == !config.templateUrl) { throw ... }
代码清晰度和可读性显然是可恶的。
+! 使用隐式转换来根据其布尔值将值转换为0或1
大多数情况下,这是为了检查是否存在。 例如,一个空string是假的( !!"" === false
),所以是未定义的,还有一些其他的。 这是主要的两个
“Falsey”转换
+!!"" === 0 +!!false === 0 +!!0 === 0 +!!undefined === 0 +!!null === 0 +!!NaN === 0
“Truthy”转换
+!!1 === 1 +!!true === 1 +!!"Foo" === 1 +!!3.14 === 1 +!![] === 1 +!!{} === 1
if((+ !! config.template)+(+ !! config.templateUrl)!== 1)
希望在这一点上更有意义。 对象config
有两个我们正在检查的属性。 .template
和.templateUrl
。 隐式转换为0或1使用+!!
将被添加,然后进行比较,以确保它不是1(这意味着它是0或2) – 属性可以是打开或closures,但不是不同的。
这里的真值表如下:
template templateUrl (+!!) + (+!!) !==1 "foo" "foo" 1 + 1 true undefined undefined 0 + 0 true undefined "" 0 + 0 true "" undefined 0 + 0 true 12 "" 1 + 0 false "" 12 0 + 1 false undefined "foo" 0 + 1 false "" "foo" 0 + 1 false "foo" "" 1 + 0 false "foo" undefined 1 + 0 false
一个更简单的方法,所有这一切只是使用隐式布尔转换
if (!config.template === !config.templateUrl)
这是一个可怕的可读性方式来写出variables的布尔值,然后使用一元转换将其转换为0/1数字结果。
考虑:
+!!true; //this converts true to false, then to true again, and true is 1 when converted +!!0; //converts 0 (falsy) to true, then false, and then the numeric 0
从技术上讲!!
不是它自己的操作符,它只是NOT( !
)操作符的两倍。
一元转换: ECMA spec doc一元加试图转换为整数。 Number()
也是一个有效的转换。
同时, ^
是按位XOR运算符。
处理小于2的数字时,如果考虑0
= false
和1
= true
, ^
将像布尔OR( ||
)一样工作。
! 是逻辑的不是操作符。 它是一个一元运算符,它的操作数转换为布尔值,然后否定它。 !!
就是那个操作员两次,第二个!
撤消否定,所以最终的结果只是转换为布尔值。
+是一元加运算符,它将操作数转换为数字。 在布尔值的情况下,false变为0
,true变为1
。
所以,如果expression式是真的, +!!(expression)
评估为1
如果expression式是假的,则评估为0
。
if ((+!!config.template) + (+!!config.templateUrl) !== 1) { 0 + 0 !== 1 true 0 + 1 !== 1 false 1 + 0 !== 1 false 1 + 1 !== 1 true
等于
if (!config.template === !config.templateUrl) {
尽pipe这两个属性的内容。