我看到一些代码似乎使用了我不认识的运算符,以两个感叹号的形式,像这样:!!。有人能告诉我这个接线员做什么吗?

我看到这件事的背景是,

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

它将Object转换为布尔值。如果为假(例如,0、null、undefined等),则为假,否则为真。

!object  // Inverted Boolean
!!object // Noninverted Boolean, so true Boolean representation

所以不是操作员;这只是!操作员两次。

这样做可能更简单:

Boolean(object) // Boolean

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

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

如果你⇒

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

但如果你⇒

console.log(!!navigator.userAgent.match(/MSIE 8.0/));
// Returns either true or false

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

true === !!10

false === !!0

看来是!!运算符导致双重否定。

var foo = "Hello, World!";

!foo // Result: false
!!foo // Result: true

我怀疑这是C++遗留下来的东西,在那里人们会重写!运算符,但不是布尔运算符。

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


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


它将后缀转换为布尔值。


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

! 表示不。所以真是假的,而且!假是真!0为真,并且!1为假。

所以你要将一个值转换成布尔值,将其反转,然后再次反转。

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

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

// And finally, much easier to understand:
val.enabled = (userId != 0);

// Or just
val.enabled = Boolean(userId);

注意:由于!=运算符的作用以及哪些值被认为是正确的。


这是一次双重手术。第一个!将值转换为布尔值并反转其逻辑值。第二个!反转逻辑值。


! 是“Boolean not”,这实际上是将“enable”的值类型化为其布尔值的相反值。第二个!翻转此值。所以enable表示“不启用”,将enable值作为布尔值。


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

除了这些黑客,您还可以使用与基元类型相对应的构造函数(不使用new)来显式转换值,即。,

Boolean(foo) === !!foo
Number(foo)  === +foo
String(foo)  === ''+foo

它不是一个操作员;它是两个。它相当于以下内容,是将值转换为布尔值的快速方法。

val.enabled = !(!enable);

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


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


这是检查未定义、“未定义”、null、“null”、“”

if (!!var1 && !!var2 && !!var3 && !!var4 ){
   //... some code here
}

!!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!

沏茶:

!! 不是运算符。这是双重用途!--这是逻辑“not”运算符。


理论上:

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

事实是假的不是真的(这就是为什么!假的结果真实)事实是真的不是假的(这就是为什么!真的结果假)


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

事实是真的不是假的(这就是为什么!!真的结果是真的)事实是,假的不是假的(这就是为什么!!假的结果是假的)


我们希望在比较中确定的是参考值的“真相”,而不是参考本身的值。在一个用例中,我们可能想知道值的真实性,即使我们希望值为false(或false),或者如果我们希望值不是布尔类型。


在实践中:

考虑一个简洁的函数,它通过动态类型(也称为“鸭子类型”)来检测特性功能(在本例中,还包括平台兼容性)。如果用户的浏览器支持HTML5<audio>元素,我们希望编写一个返回true的函数,但如果<audio<未定义,我们不希望该函数抛出错误;我们不想使用try。。。捕捉以处理任何可能的错误(因为它们很严重);此外,我们也不希望在函数中使用无法始终揭示功能真相的检查(例如,document.createElement('audio')仍将创建一个名为<audio>的元素,即使不支持HTML5<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

每个函数都接受一个<tag>参数和一个要查找的属性,但它们都会根据比较结果返回不同的值。

但等等,还有更多!

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

// 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

我们离题了。。。

无论这些情况多么罕见,可能存在一些情况,其中最简洁、最高效,因此最优选的从非布尔值(可能是未定义的值)获得真值的方法确实是使用!!。希望这可笑地澄清了这一点。


这个构造是将任何JavaScript表达式转换为它的布尔等价物。

例如:!!“他击落了我”==真的!!0===假。


这里有很多很棒的答案,但如果你读到这里,这帮助我“找到答案”。在Chrome(等)中打开控制台,然后开始键入:

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

当然,这些都和仅仅打字一样!!但添加的括号可能有助于使其更易于理解。


a = 1;
alert(!a) // -> false : a is not not defined
alert(!!a) // -> true : a is not not defined

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

!!a与相同!(!a)。如果定义了a,则a为真!a是假的,而且!!a为真。


以下是AngularJS的一段代码:

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将是真的,还有一个!这将是错误的。


这么多答案做了一半的工作。对X可以理解为“X的真实性[表示为布尔值]”。但是实际上,对于弄清楚一个变量是真是假(或者即使很多变量都是真的)来说,不是那么重要!!myVar==true与myVar相同。比较!!将X转换为“真实”布尔值并不是很有用。

你唯一的收获!!是以可重复、标准化(和JSLint友好)的方式检查多个变量之间的真实性的能力。

简单铸造:(

那就是。。。

0===false为false。!!0===假为真。

上面的没有那么有用。if(!0)给出的结果与if(!!0===false)相同。我想不出将变量转换为布尔值,然后与“真”布尔值进行比较的好例子。

请参阅JSLint的指示中的“==and!=”(注意:Crockford正在移动他的站点;该链接可能会在某一点上失效),了解原因:

==和!=运算符在比较之前执行类型强制。这很糟糕,因为它导致'\t\t'==0为真。这会掩盖类型错误。JSLint无法可靠地确定==是否正确使用,因此最好不要使用==和!=并始终使用更可靠的==和!==运算符。如果你只关心一个值是真的还是假的,那么就使用简短的形式(foo!=0)说吧(foo)而不是(foo==0)说(!foo)

注意,在将布尔值与数字进行比较时,有一些不直观的情况,布尔值将被转换为数字(true被转换为1,false被转换为0)。在这种情况下!!可能在精神上有用。不过,在这些情况下,您将非布尔值与硬类型布尔值进行比较,在我看来,这是一个严重的错误。如果(-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==myVar2为0==未定义,显然为假。!!myVar1==!!myVar2是!!0 === !!未定义且为真!同样的道理!(在这种情况下,两者都“具有虚假的真实性”。)

所以,你真正需要使用“布尔转换变量”的唯一地方是,如果你在检查两个变量是否具有相同的真实性,对吗?那就是,使用!!如果您需要查看两个变量是否都是真的或都是假的,也就是说,是否具有相等的真实性。

我想不出一个很棒的、不做作的用例。也许您在表单中“链接”了字段?

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日,2月19日:

期望显式布尔值的第三方库

这是一个有趣的案例!!当第三方库需要显式布尔值时,可能很有用。

反应

例如,JSX(React)中的False有一个特殊的含义,它不会在简单的错误中触发。如果您尝试在JSX中返回以下内容,则messageCount中应为int。。。

{messageCount&&<div>您有消息!</div>}

…当您没有消息时,您可能会惊讶地看到React呈现0。您必须显式返回false,以便JSX不呈现。上面的语句返回0,JSX很高兴地将其呈现出来。它不能告诉你没有计数:{messageCount}。

一个修复方法涉及bangbang,它将0强制为!!0,这是错误的:{!!messageCount&&<div>您有消息!</div>}JSX的文档建议您更加明确,编写自我注释代码,并使用比较强制转换为布尔值。{messageCount>0&&<div>您有消息!</div>}我自己用三元表处理错误更舒服--{messageCount?<div>您有消息!</div>:false}

TypeScript(类型脚本)

TypeScript中的相同处理:如果你有一个返回布尔值的函数(或者你正在给布尔变量赋值),你(通常)不能返回/赋值布尔值;它必须是强类型布尔值。这意味着,iff myObject是强类型的,返回!myObject;适用于返回布尔值的函数,但返回myObject;不。你必须回来!!myObject(或以另一种方式转换为正确的布尔值)以匹配TypeScript的期望。

TypeScript的例外?如果myObject是any,那么您将返回JavaScript的Wild West,并且可以不使用!!,即使您的返回类型是布尔值。

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

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


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

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

这一事实导致了以下习惯用法,您可以在源代码中看到:

!!x // Same as Boolean(x). Note double exclamation mark

!!x是布尔(x)的简写。

第一次爆炸迫使JavaScript引擎运行Boolean(x),但它也有反转值的副作用。所以第二次爆炸消除了副作用。


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

双重否定运算符!!计算值的真值。实际上是两个操作员,哪里!!x表示!(!x),并且行为如下:

如果x为假值!x为真,并且!!x为假。如果x是真值!x为假,并且!!x为真。

当在布尔上下文的顶层使用时(if、while或?)!!从行为上讲,操作员是一个no-op。例如,if(x)和if(!!x)表示相同的意思。

实际用途

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

一种用法是将对象压缩到其真值,这样代码就不会保存对大对象的引用并保持其活动。分配!!some_big_object设置为变量,而不是some_biguobject让垃圾收集器使用它。这对于生成对象或假值(例如空值或未定义值)的情况非常有用,例如浏览器特征检测。

另一个用法,我在一个关于C对应的答案中提到了!!操作员使用“lint”工具查找常见的打字错误和打印诊断。例如,在C和JavaScript中,布尔运算的一些常见错误会产生其他输出不太布尔的行为:

如果(a=b)是赋值,然后使用b的真值;如果(a==b)是相等比较。如果(a&b)是位AND;如果(a&&b)是逻辑AND。2和5为0(假值);2&&5为真。

这个操作员向lint工具保证,您所写的就是您的意思:执行此操作,然后获取结果的真值。

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


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

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

使用逻辑not运算符两次。

这意味着!true=false和!!true=真。


我只是想补充一下

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链将返回它找到的第一个假值,这可以被馈送到if语句等。因此,如果b.foo未定义,它将返回undefined并跳过b.foo.bar语句,我们不会得到任何错误。

上面的返回未定义,但如果您有一个空字符串,false,null,0,undefined,这些值将返回,一旦我们在链中遇到它们——[]和{}都是“truthy”,我们将沿着所谓的“&&链”继续到右边的下一个值。

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

因此,(b||{}).foo与b&&b.foo相同,((b||{})/foo||{}).bar与b&&b.foo&&b.foo.bar相同。


在看到所有这些伟大的答案后,我想补充一个使用!!的理由!!。目前,我正在使用Angular 2-4(TypeScript),当我的用户未通过身份验证时,我希望将布尔值返回为false。如果他未通过身份验证,则令牌字符串将为null或“”。我可以通过使用下一段代码来实现这一点:

public isAuthenticated(): boolean {
   return !!this.getToken();
}

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

console.log(布尔值(null));//优先于布尔对象console.log(new Boolean(null).valueOf());//不建议用于转换非布尔值console.log(!!null);//一种省略调用布尔函数的方法,但本质上也是这样。//您之前看到的上下文(您的示例)var垂直;函数示例(垂直){this.vertical=垂直!==未定义!!垂直:此垂直;//让我们来细分一下:如果vertical没有被严格定义,则返回vertical的布尔值并将其设置为this.vertical。如果没有,则不要为this.vertical设置值(只需忽略它并将其重新设置为以前的值;在这种情况下,什么都没有)。返回this.vertical;}console.log(“\n---------------------”)//垂直当前未定义console.log(新示例(垂直)垂直);//这是虚假的还是真实的价值。垂直的console.log(!!new Example(vertical).s垂直);//此垂直强制值垂直=12.5;//将垂直设置为12.5,这是一个真实的值。console.log(新示例(垂直)垂直);//这是假的或真的价值。不管怎样,这都是真的console.log(!!new Example(vertical).s垂直);//此垂直强制值垂直=-0;//将vertical设置为-0,这是一个错误的值。console.log(新示例(垂直)垂直);//这个值是假的还是真的。不管怎样,这个值都是假的console.log(!!new Example(vertical).s垂直);//此垂直强制值

JavaScript中的false值强制为false,truthy值强制为true。Falsy和truthy值也可以在if语句中使用,并基本上“映射”到它们对应的布尔值。然而,您可能不会发现自己必须经常使用正确的布尔值,因为它们在输出(返回值)上大多不同。

虽然这可能看起来类似于选角,但实际上这可能只是一个巧合,并不是为布尔选角而“建造”或故意制造的。所以我们不要这么说。


为什么和如何工作

简而言之,它看起来像这样:!(!null)。然而,null是假的,所以!null将为真。然后true将为false,并且它将基本上反转回以前的状态,除了这次是一个正确的布尔值(或者甚至相反,使用真值,如{}或1)。


回到你的例子

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


垂直I/O示例

运行此示例并在输入中摆弄垂直值。查看结果强制执行的操作,以便您能够完全理解上下文的代码。在输入中,输入任何有效的JavaScript值。

如果要测试字符串,请记住包含报价。不要太在意CSS和HTML代码,只需运行此代码段并使用它。然而,您可能需要查看与DOM无关的JavaScript代码(使用Example构造函数和垂直变量)。

var vertical=document.getElementById(“vertical”);var p=document.getElementById(“结果”);函数示例(垂直){this.vertical=垂直!==未定义!!垂直:此垂直;返回this.vertical;}document.getElementById(“run”).onclick=函数(){p.innerHTML=!!(新示例(eval(vertical.value)).svertical);}输入{文本对齐:居中;宽度:5米;}按钮{边距:15.5px;宽度:14em;高度:3.4em;颜色:蓝色;}变量{颜色:紫色;}p型{边距:15px;}span注释{颜色:棕色;}<!--垂直I/O示例--><h4>垂直示例</h4><code id=“code”><var class=“var”>var</var>vertical=<input-type=“text”id=“vertical”maxlength=“9”/><span class=“comment”>//输入任何有效的JavaScript值</span></code><br/><button id=“run”>运行</button><p id=“result”></p>


!! 同时使用NOT操作两次!将值转换为布尔值并将其反转,因此使用两次,显示该值的布尔值(false或true)。这里有一个简单的例子来看看如何!!作品:

首先,您所处的位置:

var zero = 0;

那你做了!0。它将被转换为布尔值,并被计算为真,因为0是假的,因此您将得到相反的值并被转换为Boolean,因此它被计算为true。

!zero; //true

但是我们不希望值的布尔值反转,所以我们可以再次反转以获得结果!这就是为什么我们使用另一个!。

大体上使我们确定我们得到的值是布尔值,而不是假值、真值、字符串等。。。

因此,这就像在JavaScript中使用布尔函数,但将值转换为布尔值的方法更简单、更短:

var zero = 0;
!!zero; //false

它返回变量的布尔值。

相反,可以使用布尔类。

(请阅读代码说明。)

var X = "test"; // The X value is "test" as a String value
var booleanX = !!X // booleanX is `true` as a Boolean value because non-empty strings evaluates as `true` in Boolean
var whatIsXValueInBoolean = Boolean(X) // whatIsXValueInBoolean is `true` again
console.log(Boolean(X) === !!X) // Writes `true`

即,布尔(X)=!!X正在使用。

请检查下面的代码片段↓

设a=0console.log(“a:”,a)//以其类型写入值console.log(“!a:”,!a)//将“0在布尔值中不为真”写入为布尔值-因此为真。在布尔值中,0表示假,1表示真。console.log(“!!a:”,!!a)//以布尔形式写入0值。0表示错误。console.log(“Boolean(a):”,Boolean(b))//等于`!!一个`console.log(“\n”)//换行a=1console.log(“a:”,a)console.log(“!a:”,!a)console.log(“!!a:”,!!a)//以布尔形式写入1个值console.log(“\n”)//换行a=“”console.log(“a:”,a)console.log(“!a:”,!a)//将“”在布尔值中不为真,因此为真。在布尔值中,空字符串、空值和未定义值表示false,如果有字符串则表示true。console.log(“!!a:”,!!a)//将“”值写入布尔值console.log(“\n”)//换行a=“测试”console.log(“a:”,a)//以其类型写入值console.log(“!a:”,!a)console.log(“!!a:”,!!a)//以布尔形式写入“测试”值console.log(“布尔值(a)==!!a:”,布尔(a)===!!a) //写入true


它将所有的东西都强制为布尔值。

例如:

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);   // -> false
console.log(!0 === false);  // -> false
console.log(!!0 === false); // -> true

有时,有必要检查函数中是否有值,数量本身对我们来说并不重要,但它是否重要。

例如,我们想检查用户是否有专业,并且我们有一个如下的功能:

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

但答案对我们来说并不重要。我们只想检查它是否有主,我们需要一个布尔值(true或false)。我们如何得到它?

就像这样:

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

或相同

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

如果this.major有值,那么!this.major返回false,但因为值有出口,我们需要返回true,所以我们使用!两次返回正确答案!(!this.major)。


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

因为JavaScript具有所谓的“truthy”和“falsy”值,所以有些表达式在其他表达式中求值时会导致true或false条件,即使所检查的值或表达式实际上不是true或false。

例如:

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

如果该元素确实存在,则表达式将求值为true,并执行代码块。

然而:

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

…将不会导致真条件,并且代码块将不会被执行,即使元素确实存在。

为什么?因为document.getElementById()是一个“truthy”表达式,它在这个if()语句中的值为true,但它不是一个真正的布尔值true。

在这种情况下,双“not”相当简单。这只是背靠背的两个不。

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

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

and

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

将如预期的那样返回true。


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

var firstname = "test";
// Type of firstname is string

var firstNameNotEmpty = !!firstname;
// Type of firstNameNotEmpty is Boolean

JavaScript false表示“”、0、undefined和null。

JavaScript对于除零以外的数字是真的,而不是空字符串、{}、[]和new Date(),因此,

!!("test") /* Is true */
!!("") /* Is false */

const foo=“bar”;console.log(!!foo);//布尔值:真

! 对值求反(反转),并始终返回/生成布尔值。所以!”bar'将产生false(因为'bar'是truthy=>否定+布尔值=false)。附加的!运算符,该值再次被求反,因此false变为true。


记住JavaScript中对true和false的求值很重要:

具有“价值”的一切都是真实的(即真实的),例如:101,3.1415,-11,“幸运的大脑”,新建对象()当然,这是真的没有“Value”的所有内容都是假的(即falsy),例如:0,-0,“”(空字符串),未定义,无效的NaN(不是数字)当然,也是假的

应用“逻辑非”运算符(!)计算操作数,将其转换为布尔值,然后对其求反。应用两次将对求反进行求反,从而有效地将值转换为布尔。不应用运算符将只是精确值的常规赋值。示例:

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=值;指定精确的对象值,即使它不是布尔值,因此value2不一定最终是布尔值。value2=!!价值作为操作数值的双重否定的结果,指定一个保证布尔值,它相当于以下内容,但要短得多,可读性强:

if(值){value2=真;}其他{value2=false;}


!! 不是运算符。这只是!操作员两次。

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

值未定义或为空的任何对象,包括值为false的布尔对象,传递给有条件的陈述

示例:if({}){console.log(“{}是true”)}//logs:“{}是true”


!! 只是两次NOT运算符。净效果就是转换任何东西以确保布尔数据类型。例如

!!undefined为false!!0为假!!null为false!!anyobject为true!!真是真!!false是false!0为真!1为假!!'' 是假的


只是为了检查是否存在

if(!!isComplianceOnHold){
//write code here is not undefined
//if isComplianceOnHold is undefined or null will not enter in net is false
// if isComplianceOnHold is not null or even boolean net result is true and enter inside if block
}

任何值未定义或为null的对象,包括值为false的布尔对象,在传递给条件语句时其计算结果为true


这是我找到的最简单的答案:它的工作方式相当于布尔值。


你可以考虑!!以这种方式:

当第一次!应用时,变量变为布尔值,但值相反然后,第二个!只是恢复正义,并将价值恢复到原来的同等价值


简单地说!!只返回一个布尔值,如果对象不是null或undefined,则返回true,否则返回false。

你可以这么说!!object等于if(object)返回true,否则返回false。

就这么简单!