有人能解释这个“双重否定”的伎俩吗?

时间:2011-01-13 23:39:06

标签: javascript html5

我绝不是Javascript的专家,但我一直在阅读Mark Pilgrim的"Dive into HTML5"网页,他提到了一些我想要更好理解的内容。

他说:

  

最后,您使用双重否定技巧将结果强制为布尔值(true或false)。

function supports_canvas() {
  return !!document.createElement('canvas').getContext;
}

如果有人能够更好地解释这一点,我会很感激!

9 个答案:

答案 0 :(得分:244)

逻辑NOT运算符!将值转换为与其逻辑值相反的布尔值。

第二个!将前一个布尔结果转换回其原始逻辑值的布尔表示。

对于Logical NOT运算符

From these docs

  

如果单个操作数可以转换为true,则返回false;否则,返回true。

因此,如果getContext给您一个“假”值,!!将返回布尔值false。否则它将返回true

“假”值是:

  • false
  • NaN
  • undefined
  • null
  • ""(空字符串)
  • 0

答案 1 :(得分:29)

当放置在期望布尔值的上下文中时,Javascript对于被认为是“真”和“假”的内容有一组令人困惑的规则。但逻辑NOT运算符!始终生成一个适当的布尔值(常量truefalse之一)。通过链接其中两个,成语!!expression产生一个与原始表达式具有相同真实性的适当布尔值。

你为什么要打扰?因为它使您显示的功能更加可预测。如果它没有双重否定,它可能会返回undefinedFunction对象,或者与Function对象完全不同的东西。如果这个函数的调用者对返回值做了一些奇怪的事情,那么整个代码可能会出错(这里的“怪异”意味着“除了强制执行布尔上下文的操作之外的任何东西”)。双阴性成语阻止了这一点。

答案 2 :(得分:14)

在javascript中,如果给定值为true,则为1,而不是null等,使用“bang”运算符(!)将返回true。如果值为undefined,null,0或空字符串,则返回false

因此,bang运算符将始终返回一个布尔值,但它将代表您开始使用的相反值。如果您获取该操作的结果并再次“敲击”它,您可以再次反转它,但仍然以布尔结尾(而不是未定义,null等)。

使用bang两次将获取一个可能未定义,null等的值,并使其仅为false。它将采用可能为1,“真实”等的值,并使其仅为true

代码可以写成:

var context = document.createElement('canvas').getContext;
var contextDoesNotExist = !context;
var contextExists = !contextDoesNotExist;
return contextExists;

答案 3 :(得分:11)

使用!!变量可以保证对布尔值进行类型转换。

举个简单的例子:

"" == false (is true)
"" === false (is false)

!!"" == false (is true)
!!"" === false (is true)

但是,如果您正在执行以下操作,那么使用它是没有意义的:

var a = ""; // or a = null; or a = undefined ...
if(!!a){
...

if会将它强制转换为boolean,因此不需要进行隐式双负投射。

答案 4 :(得分:7)

!boolean投射“某事”/“任何内容”。

!!返回原始布尔值(并保证表达式现在是布尔值,不管以前是什么)

答案 5 :(得分:5)

第一个!将变量强制转换为布尔类型并将其反转。第二个!再次将其反转(为您检查的任何内容提供原始(正确)布尔值。)

为了清楚起见,最好使用

return Boolean(....);

答案 6 :(得分:4)

document.createElement('canvas').getContext可以评估为undefined或对象引用。 !undefined产生true![some_object]产生false。这几乎就是我们所需要的,只是倒置了。因此!!用于将undefined转换为false,将对象引用转换为true

答案 7 :(得分:3)

这与JavaScript的弱打字有关。 document.createElement('canvas').getContext是一个函数对象。通过预先添加单个!,它将它作为布尔表达式进行计算并翻转答案。通过预先添加另一个!,它会将答案翻转回来。最终结果是函数将其计算为布尔表达式,但返回实际的布尔结果而不是函数对象本身。前置!!是一种快速而又脏的方法,可以将表达式强制转换为布尔类型。

答案 8 :(得分:2)

如果document.createElement('canvas').getContext不是undefinednull,则会返回true。否则它将返回false