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

Pro*_*eur 193 javascript html5

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

他说:

最后,使用双负技巧将结果强制为布尔值(true或false).

function supports_canvas() {
  return !!document.createElement('canvas').getContext;
}
Run Code Online (Sandbox Code Playgroud)

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

use*_*716 246

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

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

Logical NOT运算符的这些文档中:

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

因此,如果getContext给出"假"值,!! 则会返回布尔值false.否则它会返回true.

"假"值是:

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


zwo*_*wol 29

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

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

  • @ Abody97列表(上面的帮助显示)既不尽可能短(`false`;其他任何东西都需要显式比较运算符),也不尽可能长(至少添加`{}`和`[]`).所以你必须记住列表而不是规则.这就是我所说的令人困惑的语言功能. (7认同)
  • 这不是一套"混乱"的规则. (3认同)

Str*_*ior 14

在javascript中,如果给定值为true,1,not 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;
Run Code Online (Sandbox Code Playgroud)


fms*_*msf 11

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

举个简单的例子:

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

!!"" == false (is true)
!!"" === false (is true)
Run Code Online (Sandbox Code Playgroud)

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

var a = ""; // or a = null; or a = undefined ...
if(!!a){
...
Run Code Online (Sandbox Code Playgroud)

if将它转换为boolean,因此不需要进行隐式双负转换.


sch*_*der 7

!将"某事"/"任何事物"投射到一个boolean.

!! 给出原始的布尔值(并保证表达式现在是一个布尔值,不管以前是什么)


jas*_*bar 6

第一个!将变量强制转换为布尔类型并将其反转.第二个!反转它(给你原始的(正确的)布尔值,无论你正在检查什么).

为清楚起见,您最好使用

return Boolean(....);
Run Code Online (Sandbox Code Playgroud)

  • `Boolean()`创建一个盒装布尔值,它的行为与`!!`创建的原始布尔值不同(例如,`typeof`将报告``object"`).因此,`!!`是首选. (5认同)
  • @Zack它不适合我.它只与'new`结合使用. (3认同)
  • 现在这是一个非常古老的线程,但如果有人像我一样在研究 bang(!!) 方法与 Boolean(val) 方法的性能时遇到这个问题,Mad Man Moon 之前的评论似乎不再正确。[jsperf.com/bang-bang-vs-boolean](https://jsperf.com/bang-bang-vs-boolean) 现在显示 Boolean(val) 方法在 Chrome 和 Firefox 中速度更快。 (3认同)