Javascript +;!!if语句中的运算符
我正在审查angularjs工厂的代码,以便更好地理解它是如何工作的。代码包含一个我不完全理解的Javascript +;!!if语句中的运算符,javascript,Javascript,我正在审查angularjs工厂的代码,以便更好地理解它是如何工作的。代码包含一个我不完全理解的if语句 在plnkr演示中,作者写道: if ((+!!config.template) + (+!!config.templateUrl) !== 1) { throw new Error('Expected modal to have exactly one of either `template` or `templateUrl`'); } 显然,通过错误消息,它正在检查这两个选项中是
if
语句
在plnkr演示中,作者写道:
if ((+!!config.template) + (+!!config.templateUrl) !== 1) {
throw new Error('Expected modal to have exactly one of either `template` or `templateUrl`');
}
显然,通过错误消息,它正在检查这两个选项中是否存在一个。我只是不确定它是如何得出结论的。我找不到有关^
或+的任何信息代码>
我的问题是:这个if语句是如何工作的?(^
或+!
或+!!
特别是)这是一种非常不可读的方法,可以写出变量的布尔值,然后使用一元转换将其转换为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(!
)操作符
一元转换:一元加号尝试转换为整数Number()
也是有效的转换。+
然后将该布尔值转换为一个数字,对于true
为1
,对于false为0
> +true
1
> +false
0
就我个人而言,在处理两个布尔人的问题时,我觉得这样写更清楚:
if (!config.template == !config.templateUrl) {
throw ...
}
显然,代码的清晰性和可读性都很糟糕。同时,^
是按位异或运算符
当处理小于2的数时,<>代码> ^ < /C> >如果你考虑<代码> 0 > />代码>=代码> false < /代码>和<代码> 1 > />代码>=代码>真< /代码>,
是逻辑非运算符。它是一个一元运算符,将其操作数转换为布尔值,然后对其求反<代码>
只是该操作符的两次,第二次
撤消求反,因此最终结果只是转换为布尔值
是一元加号运算符,用于将其操作数转换为数字。对于布尔值,false变为0
,true变为1
所以,+!!(表达式)
如果表达式为真,则计算结果为1
;如果表达式为假,则计算结果为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) {
尽管有这两个属性的内容
+!!根据布尔值,使用隐式转换将值强制转换为0或1
在很大程度上,这是为了检查是否存在。例如,一个空字符串为false(!!“”===false
),因此未定义,还有许多其他字符串。这是主要的两个
错误的转换
+!!"" === 0
+!!false === 0
+!!0 === 0
+!!undefined === 0
+!!null === 0
+!!NaN === 0
+!!1 === 1
+!!true === 1
+!!"Foo" === 1
+!!3.14 === 1
+!![] === 1
+!!{} === 1
“真实”转换
+!!"" === 0
+!!false === 0
+!!0 === 0
+!!undefined === 0
+!!null === 0
+!!NaN === 0
+!!1 === 1
+!!true === 1
+!!"Foo" === 1
+!!3.14 === 1
+!![] === 1
+!!{} === 1
如果(+!!config.template)+(+!!config.templateUrl)!==1)
希望这在这一点上更有意义。我们正在检查对象config
的两个属性.template
和.templateUrl
。使用+!!将隐式强制转换为0或1代码>将被添加,然后进行比较,以确保它不是1(这意味着它不是0或2)-属性可以是开或关,但不能不同
此处的真值表如下所示:
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)
^是javascript按位异或运算符。我无法找到有关^or+的任何信息代码>您没有使用正确的关键字。搜索javascript操作符
,希望这是将简单代码放入代码模糊器的结果,因为人类不可能编写这样的代码。是的,对。是我还是“这个神秘的操作符是什么(实际上只是两个以上的操作符没有空格地粘在一起)”的问题最近出现得更多了?代码>=两个逻辑not运算符<代码>+
=一元加:;该组合可用于将truthy/falsy条件转换为整数。Number
在这里是一个合适的替代品,但是parseInt
在将布尔值转换为数字时不会有用,对吗?我经常听到这样的理由:“这段代码是如此复杂/复杂/重要/无论什么,如果你不知道如何像手背一样解析这些运算符,你就不应该再处理这段代码了。”但老实说,我听到的只是“让我们让这段极其复杂的代码更难解析!”!“不正确。parseInt(!!.x)
与+!!.x
不同。前者是NaN
。除了正确性之外,我不确定可怕的可读性原理是什么。+.x
是成功的和明确的。(尽管表达式作为一个整体可以简化为Matt指出的。)请注意,如果这两个确实是布尔值,那么您也可以编写if(config.template==config.templateUrl){}
…但是,其中一个或两个可能是字符串,而另一个可能是未定义的或null
,这就是为什么!
运算符起作用。如果(模板和模板URL)抛出新错误(“看到模板和templateUrl;您实际上想使用哪一个?”);如果(!template&&!templateUrl)抛出新错误(“既没有看到模板也没有模板URL,我没有任何东西要渲染!”);
我个人不喜欢+!!
,但值得注意的是,它将扩展到“预期正好指定{3件事情}中的1件”“更干净。在我看来,最具可读性的应该是if(truthyCount(item1,item2,item3)!==1)
@torazaburo我很确定它是正确的。。。在XOR的周围有一个外部的否定。我的大脑放屁了吗?@torazaburo我可以展示我的工作:对于布尔人A
和B
,(A异或B)
与(A!=B)
相同。因此!(A或B)
相当于!(A!=B)
或者更简单地说,A==B
。就个人而言,我认为独家or版本(来自OP)是mos