我并不是 Javascript 的专家,但我一直在阅读 Mark Pilgrim 的《深入浅出 HTML5》网页,并看到了他提到的一个我想更好地理解的东西。
他说:
最后,您可以使用双重否定技巧将结果强制转换为布尔值(true 或 false)。
function supports_canvas() {
return !!document.createElement('canvas').getContext;
}
如果有人能够更好地解释一下这个问题,我会非常感激!
我并不是 Javascript 的专家,但我一直在阅读 Mark Pilgrim 的《深入浅出 HTML5》网页,并看到了他提到的一个我想更好地理解的东西。
他说:
最后,您可以使用双重否定技巧将结果强制转换为布尔值(true 或 false)。
function supports_canvas() {
return !!document.createElement('canvas').getContext;
}
如果有人能够更好地解释一下这个问题,我会非常感激!
逻辑非运算符 !
将一个值转换为它的逻辑值相反的布尔值。
第二个 !
将上一个布尔结果转换回原始逻辑值的布尔表示。
从这份文档 中了解逻辑非运算符:
如果操作数可以转换为 true,则返回 false;否则,返回 true。
因此,如果 getContext
返回一个"假值",那么 !!
将会使它返回布尔值 false
。否则,它将返回 true
。
"假值"包括以下内容:
false
NaN
undefined
null
""
(空字符串)0
Javascript有一套混乱的规则,用于在期望布尔值的上下文中确定何为“真”和“假”。 但是,逻辑非运算符!
总是生成一个正确的布尔值(常量之一true
和false
)。通过链接两个逻辑非运算符,习惯用法!!expression
可以生成具有与原始表达式相同truthiness的正确布尔值。
为什么要这样做?因为它使得像您展示的函数更加可预测。如果没有双重否定,它可能会返回undefined
、Function
对象或类似于Function
对象的某些内容。如果此函数的调用者对返回值进行奇怪的操作,整个代码可能会表现不正常(这里的“奇怪”意味着“除了强制布尔值上下文之外的任何操作”)。双重否定习惯用法可以防止这种情况发生。
false
,任何其他情况都需要显式比较运算符),也不是最长的(至少要添加{}
和[]
)。因此,你必须记住列表而不是规则。这就是我所说的令人困惑的语言特性。 - zwolvar context = document.createElement('canvas').getContext;
var contextDoesNotExist = !context;
var contextExists = !contextDoesNotExist;
return contextExists;
"" == false (is true)
"" === false (is false)
!!"" == false (is true)
!!"" === false (is true)
但是如果你在做类似于以下的事情,使用它就没有意义:
var a = ""; // or a = null; or a = undefined ...
if(!!a){
...
如果条件语句会将其转换为布尔值,因此无需进行隐式的双重否定转换。
!
将 "something"/"anything" 转换为 boolean
类型。
!!
返回原始的 boolean 值(并确保表达式现在是一个 boolean,而不管之前是什么类型)。
第一个!
将变量强制转换为布尔类型并反转它。第二个!
再次反转它(给你检查的原始(正确)布尔值)。
为了清晰起见,最好使用
return Boolean(....);
Boolean()
创建了一个装箱后的布尔值,它的行为与通过 !!
创建的原始布尔值不同(例如,typeof
将报告 "object"
)。因此,推荐使用 !!
。 - zwolreturn (new Boolean(...)).valueOf()
- sergnew
结合时才会起作用。 - alexdocument.createElement('canvas').getContext
可能会评估为undefined
或对象引用。 !undefined
产生true
,![some_object]
产生false
。这几乎是我们需要的,只是相反。因此,!!
用于将undefined
转换为false
,将对象引用转换为true
。
这与JavaScript的弱类型有关。 document.createElement('canvas').getContext
是一个函数对象。通过在前面加上单个!
,它将其作为布尔表达式进行评估并翻转答案。再次添加!
,它会将答案翻转回来。最终结果是该函数将其作为布尔表达式进行评估,但返回的实际上是布尔结果,而不是函数对象本身。在表达式转换为布尔类型时,快速脏方式是在前面添加!!
。
document.createElement('canvas').getContext
不是undefined
或null
,它将返回true
。否则,它将返回false
。
-0 === 0 // true
user113716没有错过与问题相关的任何内容。 - user11069250
总是假值。这就是他的答案所陈述的。-0 === 0
表明它们是相同类型的相等值,因为它们是这样定义的。你的除法示例是一个非常特殊的情况,与这个问题或0
值的99.999% 的用途无关。甚至.toString()
也以相同的方式表示它们。(-0).toString(); // "0"
- user1106925Object.is(0, -0)
返回false
,因此它们不是同一件事情。 - Sebastian Simon