在JavaScript中何时使用双重非(!!)运算符

36

我理解JavaScript中的双非运算符是什么意思。但我对它的使用很好奇,我不确定我最近的一个说法是否正确。

我说if (!!someVar)(!!someVar && ...都没有意义,因为if&&都会将someVar作为布尔值进行评估,所以!!是多余的。

实际上,我只能想到这样使用双非运算符是合法的,即如果您想要与另一个布尔值进行严格比较(因此可能在期望显式true或false的返回值中)。

这正确吗?当我注意到jQuery 1.3.2同时使用if (!!someVar)return !!someVar && ...时,我开始怀疑自己。

在这些情况下,双重否定有任何实际效果吗?

我的个人意见是,它只会导致混淆。如果我看到一个if语句,我知道它正在将其评估为布尔值。


2
请注意,正如贾斯汀在他回答你所引用的问题中指出的那样(http://stackoverflow.com/questions/1406604/what-does-the-operator-double-exclamation-point-mean-in-javascript/1407785#1407785),没有双非运算符。 !! 只是将非运算符应用两次。 - outis
1
这个“运算符”是惯用语的典范... 除非你知道它是什么,否则你很可能会感到困惑,或者只是将其误读为单个的“not”。我打算开始使用它来困惑我的同事 :D 如果有人感兴趣,我在 jQuery.grep 中看到了这个“运算符”。 - Sprague
1
关于编程:if(!!condition) 和 if(condition) 的区别是什么?(链接:http://stackoverflow.com/q/19818574/1048572) - Bergi
2个回答

43
if语句的上下文中,我完全同意你,因为内部会在条件表达式上执行ToBoolean操作(请参见规范的第3步)。但是,如果你想从函数中返回一个布尔值,你应该确保结果实际上是布尔值,例如:
function isFoo () {
  return 0 && true;
}

console.log(isFoo()); // will show zero
typeof isFoo() == "number";

总之,布尔逻辑运算符 可以返回操作数,而不一定是一个Boolean结果:
逻辑AND运算符(&&)将在第一个操作数为真时返回第二个操作数的值。
true && "foo"; // "foo"

如果第一个操作数本身是“falsy”,它将返回第一个操作数的值:

NaN && "anything"; // NaN
0 && "anything"; // 0

另一方面,逻辑或运算符(||)将返回第二个操作数的值,如果第一个操作数是假值:
false || "bar"; // "bar"

如果第一个操作数本身不是假值,则会返回其值:

"foo" || "anything"; // "foo"

也许值得一提的是,以下为“假值”:nullundefinedNaN0、长度为零的字符串,当然还有false
布尔上下文中评估的任何其他内容(不是“假值”,也不是Boolean对象或Boolean值),都将返回true

另一种说法是:逻辑 AND 运算符返回遇到的第一个“假值”操作数,而逻辑 OR 运算符返回遇到的第一个“真值”操作数。此外,为了完整起见,-0 也被认为是“假值”。 - TMcManemy
如果你处于需要 !!expr 的情况下,请考虑写成 Boolean(expr),以增强可读性,因为它在功能上是等效的。 - conny
这是我经常遇到的一个用例:在JSX中进行短路渲染。如果您尝试呈现零长度数组的元素,则可能会呈现“0”。我制作了一个CodePen来演示:https://codepen.io/lucask42/full/GGbqdv/ - Lucas Kellner

0

是的,当您想要返回0或1的值时,使用!!var。

一种简单的比较bool值的方法,当您希望"a == b"等同于"a xor not b",除了a=5且b=7都为true但不相等之外。

另一种情况是当您想将一组条件强制转换为变量的位时:

 var BIT_NONEMPTY=1;
 var BIT_HASERRORS=2;
 var BIT_HASCHILDREN=4;
 var BIT_HASCONTENT=8;

 result_bitfields = 
    (!!countLines())*BIT_NOTEMPTY +
    (!!errorCode())*BIT_HASERRORS +
    (!!firstChild())*BIT_HASCHILDREN +
    (!!getContent())*BIT_HASCONTENT;

在 JavaScript 中并不是非常有用,因为它与位值相距甚远,但有时可能会有用。


3
"no":!! 转换为 false 或 true,而不是 0 或 1。(在您的位域示例中,true 然后由 * 运算符强制转换为 1,false 强制转换为 0)。 - Doin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接