3783

我看到一些代码似乎使用了我不认识的运算符,以两个感叹号的形式出现,如下所示:!!. 有人可以告诉我这个操作员是做什么的吗?

我看到这个的背景是,

this.vertical = vertical !== undefined ? !!vertical : this.vertical;
4

38 回答 38

3370

转换Objectboolean. 如果它是假的(例如,,,0nullundefined,它将是false,否则,true

!oObject  // inverted boolean
!!oObject // non inverted boolean so true boolean representation

所以!!不是运算符,它只是!运算符两次。

真实世界示例“测试 IE 版本”:

const isIE8 = !! navigator.userAgent.match(/MSIE 8.0/);  
console.log(isIE8); // returns true or false 

如果你⇒</p>

console.log(navigator.userAgent.match(/MSIE 8.0/));  
// returns either an Array or null  

但是如果你⇒</p>

console.log(!!navigator.userAgent.match(/MSIE 8.0/));  
// returns either true or false
于 2009-04-24T08:18:07.963 回答
945

这是进行类型转换的一种非常晦涩的方法。

!表示。如此,如此。!true_ 是,并且是。false!falsetrue!0true!1false

因此,您将一个值转换为布尔值,然后将其反转,然后再次反转它。

// Maximum Obscurity:
val.enabled = !!userId;

// Partial Obscurity:
val.enabled = (userId != 0) ? true : false;

// And finally, much easier to understand:
val.enabled = (userId != 0);
于 2009-09-10T17:28:36.633 回答
544

!!expr(两个!运算符后跟一个表达式)根据表达式的真实性true返回一个布尔值(或) 。在非布尔类型上使用时更有意义。考虑这些示例,尤其是第三个示例及以后的示例:false

          !!false === false
           !!true === true

              !!0 === false
!!parseInt("foo") === false // NaN is falsy
              !!1 === true
             !!-1 === true  // -1 is truthy
          !!(1/0) === true  // Infinity is truthy

             !!"" === false // empty string is falsy
          !!"foo" === true  // non-empty string is truthy
        !!"false" === true  // ...even if it contains a falsy value

     !!window.foo === false // undefined value is falsy
      !!undefined === false // undefined primitive is falsy
           !!null === false // null is falsy

             !!{} === true  // an (empty) object is truthy
             !![] === true  // an (empty) array is truthy; PHP programmers beware!
于 2012-05-15T09:06:18.150 回答
186

泡茶:

!!不是运算符。它是!-- 的双重用途,它是逻辑“非”运算符。


理论上:

!确定值不是什么的“真相”:

  • 事实是false不是true(这就是为什么!false结果true

  • 事实是true不是false(这就是为什么!true结果false


!!确定一个值不是什么的“真相” :

  • 事实true并非如此 true(这就是为什么!!true结果true

  • 事实false并非如此 false(这就是为什么!!false结果false


我们希望在比较中确定的是关于引用值的“真相”,而不是引用本身的值。有一个用例,我们可能想知道一个值的真相,即使我们期望该值是false(或错误的),或者如果我们期望该值不是 typeof boolean


在实践中:

考虑一个简洁的函数,它通过动态类型(又名“鸭子类型”)检测特性功能(在这种情况下是平台兼容性)。我们想编写一个函数,true如果用户的浏览器支持 HTML5<audio>元素,则返回该函数,但我们不希望函数在<audio>未定义时抛出错误;而且我们不想用它try ... catch来处理任何可能的错误(因为它们很严重);而且我们不希望在函数内部使用一个不能始终揭示特性真相的检查(例如,即使不支持HTML5,document.createElement('audio')仍会创建一个名为的元素)。<audio><audio>


以下是三种方法:

// this won't tell us anything about HTML5 `<audio>` as a feature
var foo = function(tag, atr) { return document.createElement(tag)[atr]; }

// this won't return true if the feature is detected (although it works just fine)
var bar = function(tag, atr) { return !document.createElement(tag)[atr]; }

// this is the concise, feature-detecting solution we want
var baz = function(tag, atr) { return !!document.createElement(tag)[atr]; }

foo('audio', 'preload'); // returns "auto"
bar('audio', 'preload'); // returns false
baz('audio', 'preload'); // returns true

每个函数都接受 a<tag>和 an的参数attribute来查找,但它们每个都根据比较确定的内容返回不同的值。

但是等等,还有更多!

你们中的一些人可能已经注意到,在这个特定的示例中,人们可以简单地使用性能稍高的方法来检查所讨论的对象是否具有属性。有两种方法可以做到这一点:

// the native `hasOwnProperty` method
var qux = function(tag, atr) { return document.createElement(tag).hasOwnProperty(atr); }

// the `in` operator
var quux = function(tag, atr) { return atr in document.createElement(tag); }

qux('audio', 'preload');  // returns true
quux('audio', 'preload'); // returns true

我们离题...

不管这些情况多么罕见,可能存在一些场景,其中最简洁、最高效、因此最优选的true从非布尔值、可能未定义的值获取的方法确实是使用!!. 希望这可笑地清除它。

于 2013-02-22T23:45:27.920 回答
111

!!将其右侧的值转换为其等效的布尔值。(想想穷人的“类型转换”方式)。它的意图通常是向读者传达代码并不关心变量中的值是什么,而是它的真实”值是什么。

于 2009-09-10T17:26:53.457 回答
87

!!foo应用一元非运算符两次,用于转换为布尔类型,类似于使用一元加号+foo转换为数字并连接空字符串''+foo以转换为字符串。

除了这些技巧,您还可以使用与原始类型对应的构造函数(使用new)来显式转换值,即

Boolean(foo) === !!foo
Number(foo)  === +foo
String(foo)  === ''+foo
于 2009-09-10T21:15:16.510 回答
81

这么多答案做了一半的工作。是的,!!X可以理解为“X [表示为布尔值] 的真实性”。但是!!,实际上,对于确定单个变量是(或者即使许多变量是)真还是假来说,这并不是那么重要。!!myVar === true和刚才一样myVar。与!!X“真正的”布尔值相比并不是很有用。

您获得的唯一好处是能够以可重复的、标准化的(和 JSLint 友好的)方式!!检查多个变量的真实性

简单地铸造:(

那是...

  • 0 === falsefalse
  • !!0 === falsetrue

上面的用处不大。if (!0)给你同样的结果if (!!0 === false)。我想不出将变量转换为布尔值然后与“真实”布尔值进行比较的好案例。

请参阅JSLint 的指示中的“== 和!=” (注意:Crockford 正在稍微移动他的网站;该链接可能会在某个时候失效)以了解原因:

== 和 != 运算符在比较之前进行强制类型转换。这很糟糕,因为它会导致 ' \t\r\n' == 0 为真。这可以掩盖类型错误。JSLint 无法可靠地确定 == 是否被正确使用,因此最好不要使用 == 和 != 并始终使用更可靠的 === 和 !== 运算符。

如果你只关心一个值是真还是假,那么使用简写形式。代替
(foo != 0)

说啊
(foo)

而不是
(foo == 0)


(!foo)

请注意,在将布尔值与数字进行比较时,存在一些不直观的情况,即布尔值将被强制转换为数字(true被强制转换为1falseto 0)。在这种情况下,!!可能在精神上有用。但是,在这些情况下,您将非布尔值与硬类型的布尔值进行比较,这在 imo 中是一个严重的错误。 if (-1)仍然是这里的路。

╔═══════════════════════════════════════╦═══════════════════╦═══════════╗
║               Original                ║    Equivalent     ║  Result   ║
╠═══════════════════════════════════════╬═══════════════════╬═══════════╣
║ if (-1 == true) console.log("spam")   ║ if (-1 == 1)      ║ undefined ║
║ if (-1 == false) console.log("spam")  ║ if (-1 == 0)      ║ undefined ║
║   Order doesn't matter...             ║                   ║           ║
║ if (true == -1) console.log("spam")   ║ if (1 == -1)      ║ undefined ║
╠═══════════════════════════════════════╬═══════════════════╬═══════════╣
║ if (!!-1 == true) console.log("spam") ║ if (true == true) ║ spam      ║ better
╠═══════════════════════════════════════╬═══════════════════╬═══════════╣
║ if (-1) console.log("spam")           ║ if (truthy)       ║ spam      ║ still best
╚═══════════════════════════════════════╩═══════════════════╩═══════════╝

根据您的引擎,事情会变得更加疯狂。例如,WScript 赢得了奖项。

function test()
{
    return (1 === 1);
}
WScript.echo(test());

由于某些历史悠久的 Windows jive,这将在消息框中输出 -1 !在 cmd.exe 提示符下试试看!但WScript.echo(-1 == test())仍然给你 0,或 WScript 的false. 移开视线。太可怕了

比较真实性:)

但是,如果我有两个值需要检查相等的真/假怎么办?

假设我们有myVar1 = 0;myVar2 = undefined;

  • myVar1 === myVar20 === undefined而且显然是错误的。
  • !!myVar1 === !!myVar2!!0 === !!undefined而且是真的!一样的真实!(在这种情况下,两者都“具有虚假的真实性”。)

因此,您真正需要使用“布尔转换变量”的唯一地方是,如果您遇到一种情况,即检查两个变量是否具有相同的真实性,对吧?也就是说,如果您需要查看两个 vars 是否都为真或都为假(或不是),即相等(或不)值,请使用。!!

我想不出一个伟大的、非人为的用例来做这个副手。也许您在表单中有“链接”字段?

if (!!customerInput.spouseName !== !!customerInput.spouseAge ) {
    errorObjects.spouse = "Please either enter a valid name AND age " 
        + "for your spouse or leave all spouse fields blank.";
}

所以现在,如果你的配偶姓名和年龄都为真,或者配偶的名字和年龄都为假,你可以继续。否则,您只有一个具有价值的字段(或非常早的包办婚姻),并且需要在您的errorObjects收藏中创建一个额外的错误。

尽管即使在这种情况下,也!!确实是多余的。一个!足以转换为布尔值,而您只是在检查相等性。


编辑 2017 年 10 月 24 日,19 年 2 月 6 日:

需要显式布尔值的 3rd 方库

这是一个有趣的案例......!!当第 3 方库需要明确的布尔值时可能很有用。

反应

例如,JSX (React) 中的 False 有一个特殊的含义,它不会因简单的虚假而触发。如果您尝试在 JSX 中返回类似以下内容,则期待 int in messageCount...

{messageCount && <div>You have messages!</div>}

0...当您有零消息时,您可能会惊讶地看到 React 渲染 a 。您必须显式返回 false 才能使 JSX 不呈现。上面的语句返回0,JSX 会愉快地呈现它,就像它应该的那样。它不能告诉你没有Count: {messageCount}

  • 一种解决方法涉及 bangbang,它强制0转换为!!0,即false
    {!!messageCount && <div>You have messages!</div>}

  • JSX 的文档建议您更加明确,编写自注释代码,并使用比较来强制为布尔值。
    {messageCount > 0 && <div>You have messages!</div>}

  • 我更愿意自己用三元处理虚假——
    {messageCount ? <div>You have messages!</div> : false}

打字稿

Typescript 中的相同处理:如果您有一个返回布尔值的函数(或者您正在为布尔变量分配一个值),那么您 [通常] 不能返回/分配一个 boolean-y 值;它必须是强类型的布尔值。这意味着,iffmyObject是强类型的,return !myObject;适用于返回布尔值的函数,但return myObject;不是。您必须return !!myObject(或以另一种方式转换为正确的布尔值)才能匹配 Typescript 的期望。

Typescript 的例外?如果myObjectany,那么您就回到了 JavaScript 的狂野西部,并且可以在没有 的情况下返回它!!,即使您的返回类型是布尔值。

请记住,这些是 JSX 和 Typescript 约定,而不是 JavaScript 固有的约定。

但是,如果您0在渲染的 JSX 中看到奇怪的 s,请考虑松散的虚假管理。

于 2015-04-29T18:14:43.853 回答
61

它只是逻辑 NOT 运算符,两次 - 它用于将某些内容转换为布尔值,例如:

true === !!10

false === !!0
于 2009-04-24T08:18:49.317 回答
33

它将后缀转换为布尔值。

于 2009-09-10T17:27:47.033 回答
30

这是一个双重not操作。第一个!将值转换为布尔值并反转其逻辑值。第二个!反转逻辑值。

于 2009-09-10T17:28:46.493 回答
29

似乎!!运算符导致双重否定。

var foo = "Hello World!";

!foo // Result: false
!!foo // Result: true
于 2009-04-24T08:20:19.190 回答
28

它模拟了Boolean()强制转换函数的行为。NOT无论给出什么操作数,第一个都返回一个布尔值。第二个NOT否定该Boolean值,因此给出true变量的布尔值。Boolean()最终结果与对值使用函数相同。

于 2011-03-23T11:53:45.190 回答
27

!!NOT一起使用操作两次,!将值转换为 aboolean并将其反转,因此使用它两次,显示该值的布尔值(假或真)。这是一个简单的例子,看看它是如何!!工作的:

首先,你有的地方:

var zero = 0;

然后你这样做!0,它将被转换为布尔值并被评估为true,因为 0 是falsy,所以你得到反转的值并转换为布尔值,所以它被评估为true

!zero; //true

但是我们不想要反转的布尔版本的值,所以我们可以再次反转它来得到我们的结果!这就是为什么我们使用另一个!.

基本上,!!请确保我们得到的值是布尔值,而不是虚假、真实或字符串等......

所以这就像Boolean在 javascript 中使用函数,但是将值转换为布尔值的简单而短的方法:

var zero = 0;
!!zero; //false
于 2017-06-24T04:16:23.667 回答
23

!是“布尔非”,它本质上将“启用”的值类型转换为其布尔值的对立面。第二 !翻转这个值。因此,!!enable意味着“不启用”,为您enable提供布尔值。

于 2009-09-10T17:29:18.247 回答
20

我认为值得一提的是,与逻辑 AND/OR 结合的条件不会返回布尔值,而是在 && 的情况下最后成功或第一次失败,在 || 的情况下第一次成功或最后失败 的条件链。

res = (1 && 2); // res is 2
res = (true && alert) // res is function alert()
res = ('foo' || alert) // res is 'foo'

为了将条件转换为真正的布尔文字,我们可以使用双重否定:

res = !!(1 && 2); // res is true
res = !!(true && alert) // res is true
res = !!('foo' || alert) // res is true
于 2016-05-25T10:18:34.720 回答
17

这不是一个操作员,而是两个。它等效于以下内容,是一种将值转换为布尔值的快速方法。

val.enabled = !(!enable);
于 2009-09-10T21:19:09.403 回答
17

!!构造是将任何 JavaScript 表达式转换为其布尔等效项的简单方法。

例如:!!"he shot me down" === true!!0 === false

于 2014-04-09T04:29:23.453 回答
12

这个问题已经得到了相当彻底的回答,但我想补充一个我希望尽可能简化的答案,使 !! 尽可能简单地掌握。

因为 javascript 具有所谓的“真”和“假”值,所以有些表达式在其他表达式中求值时会产生真或假条件,即使被检查的值或表达式实际上不是trueor false

例如:

if (document.getElementById('myElement')) {
    // code block
}

如果该元素确实存在,则表达式将评估为真,并且将执行代码块。

然而:

if (document.getElementById('myElement') == true) {
    // code block
}

...不会产生真条件,并且即使元素确实存在,代码块也不会被执行。

为什么?因为document.getElementById()是一个“真实”的表达式,将在此if()语句中评估为真,但它不是true.

在这种情况下,双重“不”非常简单。它只是两个not背靠背。

第一个简单地“反转”真值或假值,产生一个实际的布尔类型,然后第二个“反转”它再次回到它的原始状态,但现在是一个实际的布尔值。这样你就有了一致性:

if (!!document.getElementById('myElement')) {}

if (!!document.getElementById('myElement') == true) {}

正如预期的那样,两者都会返回true。

于 2019-03-10T18:43:26.100 回答
11

我怀疑这是 C++ 的遗留物,人们会覆盖 ! 运算符,但不是布尔运算符。

因此,在这种情况下,要获得否定(或肯定)答案,您首先需要使用 ! 运算符获取布尔值,但如果您想检查肯定的情况,请使用 !!。

于 2009-04-24T08:33:39.750 回答
11

ifandwhile语句和?运算符使用真值来确定要运行的代码分支。例如,零和 NaN 数字和空字符串为假,但其他数字和字符串为真。对象为真,但未定义的值和null都为假。

双重否定运算符!!计算一个值的真值。它实际上是两个运算符,其中的!!x意思是!(!x),并且行为如下:

  • 如果x是假值,!xtrue!!xfalse
  • 如果x是一个真值,!xfalse,并且!!xtrue

if当在布尔上下文( 、while?)的顶层使用时,!!运算符在行为上是无操作的。例如,if (x)if (!!x)意思是一样的。

实际用途

然而,它有几个实际用途。

一种用途是将对象有损地压缩为其真值,这样您的代码就不会持有对大对象的引用并使其保持活动状态。分配!!some_big_object给一个变量而不是some_big_object让垃圾收集器放弃它。这对于产生对象或错误值(例如null或未定义值)的情况很有用,例如浏览器功能检测。

我在关于 C 的相应!!operator的回答中提到的另一个用途是使用“lint”工具来查找常见的拼写错误和打印诊断。例如,在 C 和 JavaScript 中,布尔运算的一些常见拼写错误会产生其他行为,其输出与布尔运算不同:

  • if (a = b)是赋值,然后使用 的真值bif (a == b)是相等比较。
  • if (a & b)是按位与;if (a && b)是逻辑与。2 & 50(假值);2 && 5是真的。

!!操作员向 lint 工具保证你写的就是你的意思:做这个操作,然后取结果的真值。

第三种用途是产生逻辑 XOR 和逻辑 XNOR。在 C 和 JavaScript 中,a && b执行逻辑与(如果双方都为真,则为真),并a & b执行按位与。a || b执行逻辑或(如果至少有一个为真,则为真),并a | b执行按位或。有一个按位异或(异或)作为a ^ b,但没有用于逻辑异或的内置运算符(如果恰好一侧为真,则为真)。例如,您可能希望允许用户在两​​个字段之一中输入文本。您可以做的是将每个转换为真值并进行比较:!!x !== !!y.

于 2016-03-06T14:46:50.283 回答
10

双布尔否定。通常用于检查值是否未定义。

于 2010-12-02T20:21:14.550 回答
10

!!x是简写Boolean(x)

第一个 bang 强制 js 引擎运行Boolean(x),但也有反转值的副作用。所以第二次爆炸消除了副作用。

于 2015-12-04T12:50:49.500 回答
10

我只是想补充一点

if(variableThing){
  // do something
}

是相同的

if(!!variableThing){
  // do something
}

但是当某些东西未定义时,这可能是一个问题。

// a === undefined, b is an empty object (eg. b.asdf === undefined)
var a, b = {};

// Both of these give error a.foo is not defined etc.
// you'd see the same behavior for !!a.foo and !!b.foo.bar

a.foo 
b.foo.bar

// This works -- these return undefined

a && a.foo
b.foo && b.foo.bar
b && b.foo && b.foo.bar

这里的技巧是&&s 的链将返回它找到的第一个 false 值——这可以提供给 if 语句等。所以如果 b.foo 是未定义的,它将返回未定义并跳过该b.foo.bar语句,我们得到 no错误。

上面的返回 undefined 但如果你有一个空字符串,false, null, 0, undefined 这些值将返回,并且一旦我们在链中遇到它们——[]并且{}都是“真实的”,我们将继续所谓的“ && 链”到右边的下一个值。

PS执行上述 ( b && b.foo) 的另一种方法是(b || {}).foo. 这些是等价的,因为如果 b 未定义,b || {}则将是{},并且您将访问空对象中的值(无错误),而不是尝试访问“未定义”中的值(导致错误)。

所以,(b || {}).foo与 相同,b && b.foo((b || {}).foo || {}).bar相同b && b.foo && b.foo.bar

于 2016-10-19T21:00:36.023 回答
10

它强制所有东西都是布尔值。

例如:

console.log(undefined); // -> undefined
console.log(!undefined); // -> true
console.log(!!undefined); // -> false

console.log('abc'); // -> abc
console.log(!'abc'); // -> false
console.log(!!'abc'); // -> true

console.log(0 === false); // -> undefined
console.log(!0 === false); // -> false
console.log(!!0 === false); // -> true
于 2018-07-25T03:52:52.473 回答
9

这里有很多很好的答案,但如果你已经读到这里,这有助于我“明白”。在 Chrome(等)上打开控制台,然后开始输入:

!(!(1))
!(!(0))
!(!('truthy')) 
!(!(null))
!(!(''))
!(!(undefined))
!(!(new Object())
!(!({}))
woo = 'hoo'
!(!(woo))
...etc, etc, until the light goes on ;)

当然,这些都与仅键入 !!someThing 相同,但添加的括号可能有助于使其更易于理解。

于 2014-04-24T13:05:49.720 回答
6

在看到所有这些很棒的答案之后,我想添加另一个使用 !!. 目前我正在使用 Angular 2-4 (TypeScript),我想false在我的用户未通过身份验证时返回一个布尔值。如果他未通过身份验证,则令牌字符串将为nullor ""。我可以通过使用下一个代码块来做到这一点:

public isAuthenticated(): boolean {
   return !!this.getToken();
}
于 2017-03-29T07:15:21.490 回答
5

这是来自angular js的一段代码

var requestAnimationFrame = $window.requestAnimationFrame ||
                                $window.webkitRequestAnimationFrame ||
                                $window.mozRequestAnimationFrame;

 var rafSupported = !!requestAnimationFrame;

他们的意图是根据 requestAnimationFrame 中函数的可用性将 rafSupported 设置为 true 或 false

通常可以通过以下方式检查来实现:

if(typeof  requestAnimationFrame === 'function')
rafSupported =true;
else
rafSupported =false;

简短的方法可能是使用!

rafSupported = !!requestAnimationFrame ;

因此,如果 requestAnimationFrame 被分配了一个函数,那么 !requestAnimationFrame 将是 false 并且还有一个!这将是真的

如果 requestAnimationFrame 是未定义的,那么 !requestAnimationFrame 将是真的,而且还有一个!这将是错误的

于 2015-03-04T08:25:35.550 回答
5

使用逻辑非运算符两次
意味着 !true = false !!true = true

于 2016-07-15T10:25:01.600 回答
5
于 2017-07-11T07:03:50.793 回答
5

记住对JavaScripttrue的评估很重要:false

  • 具有“价值”的一切都是true(即),例如:

    • 101,
    • 3.1415,
    • -11,
    • "Lucky Brain",
    • new Object()
    • 而且当然,true
  • 没有“价值”的一切都是false(即falsy),例如:

    • 0,
    • -0,
    • ""(空字符串),
    • undefined,
    • null,
    • NaN(不是数字)
    • 而且当然,false

应用“逻辑非”运算符 ( !) 计算操作数,将其转换为boolean然后取反。应用它两次将否定否定,有效地将值转换为boolean. 不应用运算符将​​只是对确切值的常规分配。例子:

var value = 23; // number
var valueAsNegatedBoolean = !value; // boolean falsy (because 23 is truthy)
var valueAsBoolean = !!value; // boolean truthy
var copyOfValue = value; // number 23

var value2 = 0;
var value2AsNegatedBoolean = !value2; // boolean truthy (because 0 is falsy)
var value2AsBoolean = !!value2; // boolean falsy
var copyOfValue2 = value2; // number 0
  • value2 = value;分配确切的对象value,即使它不是boolean因此value2不一定最终成为boolean.
  • value2 = !!value;分配一个保证boolean作为操作数的双重否定的结果,value它等价于以下但更短且可读性:

if (value) {
  value2 = true;
} else {
  value2 = false;
}

于 2021-01-21T13:52:49.983 回答
4

JavaScript 中的一些运算符执行隐式类型转换,有时用于类型转换。

一元运算!符将其操作数转换为布尔值并将其取反。

这一事实导致您可以在源代码中看到以下成语:

!!x // Same as Boolean(x). Note double exclamation mark
于 2015-07-01T07:29:12.637 回答
3

要将 JavaScript 变量转换为布尔值,

var firstname = "test";
//type of firstname is string
var firstNameNotEmpty = !!firstname;
//type of firstNameNotEmpty is boolean

javascript false for "",0,undefined and null

javascript适用于除零以外的数字,而不是空字符串、{}、[] 和 new Date() 所以,

!!("test") /*is true*/
!!("") /*is false*/
于 2019-10-29T19:56:49.890 回答
2
a = 1;
alert(!a) // -> false : a is not not defined
alert(!!a) // -> true : a is not not defined

对于!a,它检查是否a未定义同时!!a检查变量是否已定义。

!!a是一样的!(!a)。如果a定义,atrue!afalse!!atrue

于 2014-06-28T03:35:13.250 回答
2

!!类似于使用布尔构造函数,或者可以说更像布尔函数。

console.log(Boolean(null)); // Preferred over the Boolean object

console.log(new Boolean(null).valueOf()); // Not recommended for coverting non-boolean values

console.log(!!null); // A hacky way to omit calling the Boolean function, but essentially does the same thing. 


// The context you saw earlier (your example)
var vertical;

function Example(vertical)
{
        this.vertical = vertical !== undefined ? !!vertical : 
        this.vertical; 
        // Let's break it down: If vertical is strictly not undefined, return the boolean value of vertical and set it to this.vertical. If not, don't set a value for this.vertical (just ignore it and set it back to what it was before; in this case, nothing).   

        return this.vertical;
}

console.log( "\n---------------------" )

// vertical is currently undefined

console.log(new Example(vertical).vertical); // The falsey or truthy value of this.vertical
console.log(!!new Example(vertical).vertical); // Coerced value of this.vertical

vertical = 12.5; // set vertical to 12.5, a truthy value.
console.log(new Example(vertical).vertical); // The falsey or truthy value of this.vertical which happens to be true anyway
console.log(!!new Example(vertical).vertical); // Coerced value of this.vertical

vertical = -0; // set vertical to -0, a falsey value.
console.log(new Example(vertical).vertical); // The falsey or truthy value of this.vertical which happens to be false either way
console.log(!!new Example(vertical).vertical); // Coerced value of this.vertical

javascript 中的Falsey 值强制false,而真值 强制true 。假值和真值也可以在if语句中使用,并且本质上将“映射”到它们相应的布尔值。但是,您可能不会发现自己必须经常使用正确的布尔值,因为它们的输出(返回值)大多不同。

尽管这可能看起来类似于强制转换,但实际上这可能仅仅是巧合,并不是“构建”或特意为布尔类型转换而制造的。所以我们不要这样称呼它。


为什么以及如何工作

简而言之,它看起来像这样:`!(!null)`。而 `null` 是 **falsey**,所以 `!null` 会是 **true**。那么 `!true` 将是 **false** 并且它基本上会*反转回* 到它之前的状态,除了这次是*正确的布尔值*(或者甚至*反之亦然*具有*真实值*,如 ` {}` 或 `1`)。

回到你的例子

总的来说,你看到的上下文只是根据是否定义了 `vertical` 来调整 `this.vertical`,如果定义了;它将被设置为垂直的结果布尔值,否则它不会改变。换句话说,如果定义了“垂直”;`this.vertical` 将被设置为它的布尔值,否则,它将保持不变。我想这本身就是一个示例,说明您将如何使用 `!!` 以及它的作用。

垂直 I/O 示例

运行此示例并调整输入中的垂直值。查看结果强制转换为什么,以便您可以完全理解上下文的代码。在输入中,输入任何有效的 javascript 值。 如果您正在测试字符串,请记住包含引号。不要太在意 CSS 和 HTML 代码,只需运行此代码段并使用它。但是,您可能想查看非 DOM 相关的 javascript 代码(使用 Example 构造函数和垂直变量)。

var vertical = document.getElementById("vertical");
var p = document.getElementById("result");

function Example(vertical)
{
        this.vertical = vertical !== undefined ? !!vertical : 
        this.vertical;   

        return this.vertical;
}

document.getElementById("run").onclick = function()
{

  p.innerHTML = !!( new Example(eval(vertical.value)).vertical );
  
}
input
{
  text-align: center;
  width: 5em;
} 

button 
{
  margin: 15.5px;
  width: 14em;
  height: 3.4em;
  color: blue;
}

var 
{
  color: purple;
}

p {
  margin: 15px;
}

span.comment {
  color: brown;
}
<!--Vertical I/O Example-->
<h4>Vertical Example</h4>
<code id="code"><var class="var">var</var> vertical = <input type="text" id="vertical" maxlength="9" />; <span class="comment">// enter any valid javascript value</span></code>
<br />
<button id="run">Run</button>
<p id="result">...</p>

于 2017-04-17T14:47:47.180 回答
0

有时需要检查我们在函数中是否有值,数量本身对我们来说并不重要,而是它是否重要。例如,我们要检查用户是否有专业,我们有一个功能,就像:

hasMajor(){return this.major}//it return "(users major is)Science" 

但答案对我们来说并不重要,我们只想检查它是否有专业,我们需要一个布尔值(真或假)我们如何得到它:

像这样:

hasMajor(){ return !(!this.major)}

或同样

hasMajor(){return !!this.major)}

如果 this.major 有一个值,则!this.major返回 false,但是因为该值已经退出,我们需要返回 true,我们使用 ! 两次返回正确答案!(!this.major)

于 2018-09-15T04:37:21.030 回答
0

const foo = 'bar';
console.log(!!foo); // Boolean: true

!否定(反转)一个值并且总是返回/产生一个布尔值。所以 !'bar' 会产生 false (因为 'bar' 是真的 => 否定 + boolean = false)。随着额外的!运算符,该值再次被否定,因此 false 变为 true。

于 2020-07-01T09:18:27.210 回答
0

!!不是运算符,它只是 ! 操作员两次

但是使用javascript,应用!在大多数情况下,将 Object 转换为布尔值是冗余和冗长的,因为:

值不是 undefined 或 null 的任何对象,包括值为 false 的布尔对象,在传递给条件语句时评估为 true

前任: if ({}) { console.log("{} is true")} // logs: "{} is true"

于 2021-11-12T03:56:02.860 回答
-4

这是检查未定义、“未定义”、“空”、“空”、“”的一种非常方便的方法

if (!!var1 && !!var2 && !!var3 && !!var4 ){
   //... some code here
}
于 2012-04-24T12:22:05.990 回答