有人可以解释这个“双重否定”的伎俩吗?
我绝不是JavaScript的专家,但我一直在阅读Mark Pilgrim的“潜入HTML5”网页,他提到了一些我想要更好的理解的东西。
他指出:
最后,您使用双重否定技巧强制结果为布尔值(true或false)。
function supports_canvas() { return !!document.createElement('canvas').getContext; }
如果有人能更好地解释这一点,我将不胜感激!
一个逻辑NOT运算符!
将一个值转换为与其逻辑值相反的布尔值。
第二!
将之前的布尔结果转换回其原始逻辑值的布尔表示。
从逻辑NOT运算符的这些文档 :
如果其单个操作数可以转换为true,则返回false; 否则,返回true。
所以如果getContext
给你一个“假”的价值, !!
会使它返回布尔值false
。 否则,它将返回true
。
“错误”的价值是:
-
false
-
NaN
-
undefined
-
null
-
""
(空string) -
0
如果放置在期望布尔值的上下文中,那么Javascript对于被认为是“真”和“假”的规则会有一些混淆。 但逻辑NOT运算符!
总是产生一个合适的布尔值(其中一个常量true
和false
)。 通过链接它们中的两个,成语!!expression
产生与原始expression式相同的真实性的适当的布尔值。
你为什么打扰? 因为它使function像你显示更可预测的function。 如果在那里没有双重否定,它可能会返回undefined
,一个Function
对象,或者与Function
对象完全不同的东西。 如果这个函数的调用者用返回值做了一些奇怪的事情,那么整个代码可能会行为不端(这里的“怪异”意思是“除了强制布尔上下文的操作之外的任何事情”)。 双重负面的习语可以防止这种情况发生。
在JavaScript中,如果给定值为真,则使用“bang”运算符(!)将返回true,如果值为undefined,null,0或空string,则返回false。
所以bang运算符总是会返回一个布尔值,但是它会代表你开始的相反的值。 如果你把这个操作的结果再次“敲打”一遍,你可以反转一遍,但是最后还是一个布尔值(而不是未定义的,null等)。
使用bang两次将会得到一个可能未定义的值,null等等,并且只是简单的false
。 这将需要一个值,可能是1,“真实”等,并使其显然是true
。
代码可以写成:
var context = document.createElement('canvas').getContext; var contextDoesNotExist = !context; var contextExists = !contextDoesNotExist; return contextExists;
使用!!variables可以保证types转换为布尔值。
给你一个简单的例子:
"" == false (is true) "" === false (is false) !!"" == false (is true) !!"" === false (is true)
但是,如果你正在做类似的事情,那么使用它是没有意义的:
var a = ""; // or a = null; or a = undefined ... if(!!a){ ...
if会将其转换为布尔值,因此不需要进行隐式双重负投。
!
将“something”/“anything”转换为boolean
。
!!
给出原来的布尔值(并保证expression式是一个布尔值,不pipe之前是什么)
第一!
强制该variables为布尔types并将其反转。 第二!
再次翻转它(给你原来的(正确的)布尔值,无论你正在检查)。
为了清楚起见,你最好使用
return Boolean(....);
document.createElement('canvas').getContext
可能会评估为undefined
或对象引用。 !undefined
yield true
, ![some_object]
产生false
。 这几乎是我们所需要的,只是倒过来。 所以!!
用于将undefined
转换为false
并将对象引用转换为true
。
这与JavaScript的弱types有关。 document.createElement('canvas').getContext
是一个函数对象。 通过预先一个!
它评估它作为一个布尔expression式,并翻转周围的答案。 通过预先计划另一个!
,它翻转答案。 最终结果是该函数将其评估为布尔expression式,但返回实际的布尔结果而不是函数对象本身。 预先!!
是一种将expression式转换为布尔types的快速且肮脏的方法。
如果document.createElement('canvas').getContext
不是undefined
或为null
,则返回true
。 否则,它将返回false
。