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

我看到这件事的背景是,

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

当前回答

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

其他回答

这么多答案做了一半的工作。对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,请考虑松散的错误管理。

沏茶:

!! 不是运算符。这是双重用途!--这是逻辑“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

我们离题了。。。

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

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

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

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)。

只是为了检查是否存在

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

它返回变量的布尔值。

相反,可以使用布尔类。

(请阅读代码说明。)

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