Javascript 有人可以解释这个“双重否定”的把戏吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4686583/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 13:37:25  来源:igfitidea点击:

Can someone explain this 'double negative' trick?

javascripthtml

提问by ProfessionalAmateur

I am by no means an expert at Javascript, but I have been reading Mark Pilgrim's "Dive into HTML5"webpage and he mentioned something that I would like a better understanding of.

我绝不是 Javascript 方面的专家,但我一直在阅读 Mark Pilgrim 的“Dive into HTML5”网页,他提到了一些我希望更好地理解的内容。

He states:

他说:

Finally, you use the double-negative trick to force the result to a Boolean value (true or false).

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

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

If anyone can explain this a little better I would appreciate it!

如果有人能更好地解释这一点,我将不胜感激!

回答by user113716

A logical NOT operator !converts a value to a boolean that is the opposite of its logical value.

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

The second !converts the previous boolean result back to the boolean representation of its original logical value.

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

From these docsfor the Logical NOT operator:

从这些关于逻辑非运算符的文档中:

Returns false if its single operand can be converted to true; otherwise, returns true.

如果它的单个操作数可以转换为真,则返回假;否则,返回真。

So if getContextgives you a "falsey" value, the !!will make it return the boolean value false. Otherwise it will return true.

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

The "falsey" values are:

“falsey”值是:

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

回答by zwol

Javascript has a confusing set of rules for what is considered "true" and "false" when placed in a context where a Boolean is expected. But the logical-NOT operator, !, always produces a proper Boolean value (one of the constants trueand false). By chaining two of them, the idiom !!expressionproduces a proper Boolean with the same truthiness as the original expression.

当放置在需要布尔值的上下文中时,Javascript 对什么被认为是“真”和“假”有一组令人困惑的规则。但是逻辑非运算符 ,!总是产生一个正确的布尔值(常量true和 之一false)。通过将其中的两个链接起来,习语!!expression会生成一个与原始表达式具有相同真实性的正确布尔值。

Why would you bother? Because it makes functions like the one you show more predictable. If it didn't have the double negative in there, it might return undefined, a Functionobject, or something not entirely unlike a Functionobject. If the caller of this function does something weird with the return value, the overall code might misbehave ("weird" here means "anything but an operation that enforces Boolean context"). The double-negative idiom prevents this.

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

回答by StriplingWarrior

In javascript, using the "bang" operator (!) will return true if the given value is true, 1, not null, etc. It will return false if the value is undefined, null, 0, or an empty string.

在 javascript 中,如果给定的值为真、1、非空等,使用“bang”运算符 (!) 将返回真。如果值为未定义、空、0 或空字符串,它将返回假。

So the bang operator will always return a boolean value, but it will represent the opposite value of what you began with. If you take the result of that operation and "bang" it again, you can reverse it again, but still end up with a boolean (and not undefined, null, etc).

因此 bang 运算符将始终返回一个布尔值,但它将表示与您开始时相反的值。如果您获取该操作的结果并再次“敲打”它,您可以再次反转它,但最终仍会得到一个布尔值(而不是未定义、空值等)。

Using the bang twice will take a value that could have been undefined, null, etc, and make it just plain false. It will take a value that could have been 1, "true", etc. and make it just plain true.

使用 bang 两次将采用一个可能是 undefined、null 等的值,并使其变得简单false。它将采用一个可能是 1、“true”等的值,并使其变得简单true

The code could have been written:

代码可以写成:

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

回答by fmsf

Using !!variable gives you a guarantee of typecast to boolean.

使用 !!variable 可以保证将类型转换为布尔值。

To give you a simple example:

给你一个简单的例子:

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

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

But it doesn't make sense to use if you are doing something like:

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

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

The if will cast it to boolean so there is no need to make the implicit double negative cast.

if 将其强制转换为布尔值,因此无需进行隐式双重否定转换。

回答by schnaader

!casts "something"/"anything" to a boolean.

!将 "something"/"anything" 转换为boolean.

!!gives the original boolean value back (and guarantees the expression is a boolean now, regardless to what is was before)

!!返回原始布尔值(并保证表达式现在是布尔值,无论之前是什么)

回答by jasonbar

The first !coerces the variable to a boolean type and inverts it. The second !inverts it again (giving you the original (correct) boolean value for whatever you are checking).

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

For clarity you would be better off using

为了清楚起见,您最好使用

return Boolean(....);

回答by 9000

document.createElement('canvas').getContextmay evaluate to either undefinedor an object reference. !undefinedyields true, ![some_object]yields false. This is almost what we need, just inverted. So !!serves to convert undefinedto falseand an object reference to true.

document.createElement('canvas').getContext可以评估为undefined或对象引用。!undefined产量true![some_object]产量false。这几乎就是我们需要的,只是倒过来了。So!!用于转换undefinedfalse和对象引用到true.

回答by Jim

It's to do with JavaScript's weak typing. document.createElement('canvas').getContextis a function object. By prepending a single !it evaluates it as a boolean expression and flips the answer around. By prepending another !, it flips the answer back. The end result is that the function evaluates it as a boolean expression, but returns an actual boolean result rather than the function object itself. Prepending !!is a quick and dirty way to typecast an expression to a boolean type.

这与 JavaScript 的弱类型有关。 document.createElement('canvas').getContext是一个函数对象。通过在前面加上一个,!它将它评估为一个布尔表达式并翻转答案。通过添加 another !,它将答案翻转回来。最终结果是该函数将其计算为布尔表达式,但返回实际的布尔结果而不是函数对象本身。前置!!是将表达式类型转换为布尔类型的一种快速而肮脏的方式。

回答by nyuszika7h

If document.createElement('canvas').getContextisn't undefinedor null, it will return true. Otherwise it will return false.

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