javascript中的运算符!!是什么意思?

What is the !! (not not) operator in JavaScript?

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

我看到的背景是,

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


强制oObject为布尔值。如果是虚假的(如0、nullundefined等),则为false,否则为true

1
2
!oObject  //Inverted boolean
!!oObject //Non inverted boolean so true boolean representation

所以!!不是一个操作符,它只是!操作符的两次。

现实世界中的"测试IE版本"示例:

1
2
3
let isIE8 = false;  
isIE8 = !! navigator.userAgent.match(/MSIE 8.0/);  
console.log(isIE8); // returns true or false

如果你?

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

但是如果你?

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


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

!不是。所以!truefalse!falsetrue!0true!1false

所以你要把一个值转换成一个布尔值,然后反转它,然后再反转它。

1
2
3
4
5
6
7
8
// Maximum Obscurity:
val.enabled = !!userId;

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

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


!!expr根据表达式的真实性返回布尔值(truefalse。当用于非布尔类型时,它更有意义。考虑这些例子,尤其是第三个例子及以后的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
          !!false === false
           !!true === true

              !!0 === false
!!parseInt("foo") === false // NaN is falsy
              !!1 === true
             !!-1 === true  // -1 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 is falsy
           !!null === false // null is falsy

             !!{} === true  // an (empty) object is truthy
             !![] === true  // an (empty) array is truthy; PHP programmers beware!


沏茶:

!!不是一个运算符。它是!的双重用法,这是逻辑上的"not"运算符。

理论上:

!决定了价值不是什么的"真实性":

  • 事实是,false不是true(这就是!false结果的原因在true中)

  • 事实是,true不是false(这就是!true结果的原因在false中)

!!决定了价值不是什么的"真实性":

  • 事实上,true不是true(这就是!!true导致true的原因)

  • 事实上,false不是false(这就是!!false导致false的原因)

我们希望在比较中确定的是关于参考值的"真相",而不是参考值本身的价值。在一个用例中,我们可能想知道一个值的真实性,即使我们期望该值是false(或虚假的),或者我们期望该值不是boolean的类型。

在实践中:

考虑一个简洁的函数,它通过动态类型(也称为"duck-typing")来检测特性功能(在本例中是平台兼容性)。如果用户的浏览器支持html5 元素,我们希望编写一个返回true的函数,但是如果未定义,我们不希望函数抛出错误;我们不希望使用try ... catch来处理任何可能的错误(因为它们很严重);而且我们也不希望在函数i内使用检查。在这一点上,将无法始终揭示该特性的真实性(例如,即使不支持HTML5 ),document.createElement('audio')仍将创建一个名为的元素)。

以下是三种方法:

1
2
3
4
5
6
7
8
9
10
11
12
// this won't tell us anything about HTML5 `` 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

每个函数接受attribute要查找的参数,但它们都根据比较确定的结果返回不同的值。

但是等等,还有更多!

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

1
2
3
4
5
6
7
8
// 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的最首选方法实际上是使用!!。希望这能荒谬地解决问题。


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


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

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

1
2
3
Boolean(foo) === !!foo
Number(foo)  === +foo
String(foo)  === ''+foo


有那么多答案做了一半的工作。是的,!!X可以理解为"x的真实性[表示为布尔值]"。但实际上,对于确定一个变量是真是假(或者即使有许多变量也是真)来说,!!并不是那么重要。!!myVar === truemyVar相同。将!!X与"实数"布尔值进行比较并不是很有用。好的。

使用EDOCX1[1]所获得的好处是能够以可重复、标准化(和jslint友好)的方式检查多个变量之间的真实性。好的。简单铸造:(

那是…好的。

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

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

看"="和"!"="从JSlint的方向(注意:Crockford正在移动他的站点一点;该链接在某个点上可能会死掉)了解一点原因:好的。

The == and != operators do type coercion before comparing. This is bad because it causes ' \t

' == 0 to be true. This can mask type errors. JSLint cannot reliably determine if == is being used correctly, so it is best to not use == and != at all and to always use the more reliable === and !== operators instead.

Ok.

If you only care that a value is truthy or falsy, then use the short form. Instead of
(foo != 0)

Ok.

just say
(foo)

Ok.

and instead of
(foo == 0)

Ok.

say
(!foo)

Ok.

请注意,有些非故意的情况下,当将布尔值与数字进行比较时,会将布尔值强制转换为数字(true强制转换为1false强制转换为0。在这种情况下,!!可能在精神上有用。不过,同样地,在这些情况下,您将非布尔值与硬类型布尔值进行比较,这是一个严重的错误。if (-1)仍然是到这里的路。好的。

1
2
3
4
5
6
7
8
9
10
11
12
╔═══════════════════════════════════════╦═══════════════════╦═══════════╗
║               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赢得了奖品。好的。

1
2
3
4
5
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是真的!同样的真实!(在这种情况下,两人都"有一种虚伪的真实性"。)

所以,唯一真正需要使用"布尔值转换变量"的地方是,如果你有一种情况,你要检查两个变量是否具有相同的真实性,对吗?也就是说,如果需要查看两个变量是否都是真实的,或者都是错误的(或者不是),那就使用!!,也就是说,是否具有相等的(或者不是)真实性。好的。

我不能马上想到一个伟大的,非人为的用例。也许您在表单中有"链接"字段?好的。

1
2
3
4
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日:好的。需要显式布尔值的第三方库

这是一个有趣的案例…当第三方libs期望显式的布尔值时,!!可能很有用。好的。

例如,JSX中的false(react)有一个特殊的含义,它不是由简单的伪造触发的。如果您试图在JSX中返回类似以下内容的内容,希望在messageCount中有一个int…好的。

{messageCount && You have messages!}好的。

…当您没有消息时,您可能会惊讶地看到react呈现一个0。必须显式返回false,JSX才能不呈现。上面的语句返回0,jsx很高兴地将其呈现出来。它不能告诉你没有Count: {messageCount && Get your count to zero!}(或其他不那么做作的东西)。好的。

  • 其中一个解决方案是邦邦,它将0强制为!!0,即false{!!messageCount && You have messages!}好的。

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

  • 我更愿意自己用三元数来处理错误。--{messageCount ? You have messages! : false}好的。

typescript中的处理方法相同:如果您有一个返回布尔值的函数(或者您正在为布尔变量赋值),则[通常]不能返回/赋值布尔-Y值;它必须是强类型布尔值。这意味着,如果myObject是强类型的,return !myObject;适用于返回布尔值的函数,但return myObject;不适用。您必须使用return !!myObject来匹配typescript的期望值。好的。

The exception for Typescript? If myObject was an any, you're back in JavaScript's Wild West and can return it without !!, even if your return type is a boolean.

Ok.

请记住,这些是JSX&typescript约定,而不是JavaScript固有的约定。好的。

但是,如果您在呈现的JSX中看到奇怪的0,请考虑松散的错误管理。好的。好啊。


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

1
2
3
true === !!10

false === !!0


它将后缀转换为布尔值。


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


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


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

1
2
3
4
var foo ="Hello World!";

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

!是"boolean not",它本质上把"enable"的值类型转换为它的布尔值。第二!翻转此值。因此,!!enable的意思是"不启用",它将enable的值作为布尔值。


我认为值得一提的是,与逻辑和/或组合在一起的条件不会返回布尔值,但在&;&;和条件链的第一次成功或最后一次失败。

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

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

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


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

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


不是一个接线员,是两个。它等价于以下内容,是将值强制转换为布尔值的快速方法。

1
val.enabled = !(!enable);

!!它同时使用NOT操作两次,!将值转换为boolean并反转,下面是一个简单的例子来了解!!是如何工作的:

首先,你所在的地方:

1
var zero = 0;

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

1
!zero; //true

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

基本上,!!确保我们得到的值是布尔值,而不是falsy、truthy或string等。

因此,就像在javascript中使用boolean函数一样,但将值转换为布尔值的方法简单而简短:

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

我怀疑这是一个C++的残留物,人们在上面覆盖它!但不是布尔运算符。

因此,要得到否定(或肯定)的答案,在这种情况下,您首先需要使用!运算符得到一个布尔值,但如果要检查正的情况,将使用!!


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

双负算子!!计算一个值的真值。实际上是两个操作符,其中!!x表示!(!x),其行为如下:

  • 如果x为假值,!xtrue!!xfalse
  • 如果x为真值,!xfalse!!xtrue

当在布尔上下文(ifwhile?的顶层使用时,!!运算符在行为上是一个no-op。例如,if (x)if (!!x)的含义相同。

实际用途

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

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

另一种用法是使用"lint"工具查找常见的打字错误和打印诊断,我在关于C的对应!!操作符的回答中提到过。例如,在C和JavaScript中,布尔操作的一些常见错误类型会产生其他输出不太布尔的行为:

  • if (a = b)是赋值后使用b的真值;if (a == b)是相等比较。
  • if (a & b)是位AND;if (a && b)是逻辑AND。2 & 50(虚值);2 && 5为真。

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

第三种用法是生成逻辑XOR和逻辑XNOR。在c和javascript中,a && b执行逻辑与(如果两边都为真,则为真),a & b执行位与。a || b执行逻辑或(如果至少有一个为真,则为真),a | b执行位或。有一个位异或(exclusive or)作为a ^ b,但没有内置的逻辑异或运算符(如果一侧为真,则为真)。例如,您可能希望允许用户只在两个字段中的一个字段中输入文本。你所能做的就是把每一个都转换成一个真值并进行比较:!!x !== !!y


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


这里有很多很好的答案,但如果你读到这里,这帮助我"得到它"。打开Chrome(等)上的控制台,然后开始键入:

1
2
3
4
5
6
7
8
9
10
11
!(!(1))
!(!(0))
!(!('truthy'))
!(!(null))
!(!(''))
!(!(undefined))
!(!(new Object())
!(!({}))
woo = 'hoo'
!(!(woo))
...etc, etc, until the light goes on ;)

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


!!xBoolean(x)的简写。

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


它强制所有事物都是布尔型的。

例如:

1
2
3
4
5
6
7
8
9
10
11
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

这是Angular JS的一段代码

1
2
3
4
5
var requestAnimationFrame = $window.requestAnimationFrame ||
                                $window.webkitRequestAnimationFrame ||
                                $window.mozRequestAnimationFrame;

 var rafSupported = !!requestAnimationFrame;

他们的目的是根据requestAnimationFrame中函数的可用性将rafsupported设置为true或false。

一般可通过以下方式进行检查:

1
2
3
4
if(typeof  requestAnimationFrame === 'function')
rafSupported =true;
else
rafSupported =false;

这条捷径可能会用到!!

1
rafSupported = !!requestAnimationFrame ;

因此,如果RequestAnimationFrame被分配了一个函数然后!requestAnimationFrame将为false,并且还有一个!是真的。

如果未定义RequestAnimationFrame,则!RequestAnimationFrame将是真的,而且还有一个!那是假的


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

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

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

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

我只是想补充一下

1
2
3
if(variableThing){
  // do something
}

是一样的

1
2
3
if(!!variableThing){
  // do something
}

但这可能是一个未定义的问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// a is undefined, b is empty object.
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

这里的诀窍是&&的链将返回它发现的第一个错误值——并且可以将其反馈到if语句等。因此,如果b.foo未定义,它将返回未定义并跳过b.foo.bar语句,我们不会得到错误。

上面的返回未定义,但是如果您有一个空字符串,那么,false、null、0、undefined,这些值将返回,并且一旦我们在链中遇到它们——[]{}都是真实的。


在看到这些伟大的答案之后,我想补充一下使用!!的另一个原因。目前我在Angular2-4(typescript)中工作,当我的用户没有经过身份验证时,我想返回一个布尔值作为false。如果他没有通过身份验证,令牌字符串将是null""。我可以通过使用下一个代码块来做到这一点:

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

返回变量的布尔值。

相反,可以使用boolean类。

(请阅读代码说明)

1
2
3
4
var X ="test"; // X value is"test" as a String value
var booleanX = !!X // booleanX is `true` as a Boolean value beacuse non-empty strings evaluates as `true` in boolean
var whatIsXValueInBoolean = Boolean(X) // whatIsXValueInBoolean is `true` again
console.log(Boolean(X) === !!X) // writes `true`

即使用中的Boolean(X) = !!X

请检查下面的代码段↓

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
let a = 0
console.log("a:", a) // writes a value in its kind
console.log("!a:", !a) // writes '0 is NOT true in boolean' value as boolean - So that's true.In boolean 0 means false and 1 means true.
console.log("!!a:", !!a) // writes 0 value in boolean. 0 means false.
console.log("Boolean(a):", Boolean(a)) // equals to `!!a`
console.log("
"
) // newline

a = 1
console.log("a:", a)
console.log("!a:", !a)
console.log("!!a:", !!a) // writes 1 value in boolean
console.log("
"
) // newline

a =""
console.log("a:", a)
console.log("!a:", !a) // writes '"" is NOT true in boolean' value as boolean - So that's true.In boolean empty strings, null and undefined values mean false and if there is a string it means true.
console.log("!!a:", !!a) // writes"" value in boolean
console.log("
"
) // newline

a ="test"
console.log("a:", a) // writes a value in its kind
console.log("!a:", !a)
console.log("!!a:", !!a) // writes"test" value in boolean

console.log("Boolean(a) === !!a:", Boolean(a) === !!a) // writes true


两次使用逻辑非运算符它的意思是!真=假而且!真=真


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
console.log(Boolean(null)); // Preffered 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("
---------------------"
)

// 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中的假值强制为假,而truthy值强制为真。假值和真值也可用于if语句中,并基本上"映射"到相应的布尔值。但是,您可能不会发现自己经常需要使用适当的布尔值,因为它们在输出(返回值)上的差异很大。

Although this may seem similar to casting, realistically this is likely a mere coincidence and is not 'built' or purposely made for and like a boolean cast. So let's not call it that.


为什么以及如何工作

简而言之,它看起来是这样的:! ( !null )。然而,null是假的,所以!null是真的。那么,!true将是错误的,它基本上会倒转回原来的样子,除了这一次作为一个适当的布尔值(或者甚至与真实值相反,如{}1)。

< BR>

回到你的例子

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

< BR>

垂直I/O示例

运行这个例子,并在输入中摆弄垂直值。查看结果强制执行的内容,以便您能够完全理解上下文的代码。在输入中,输入任何有效的javascript值。如果要测试字符串,请记住包括引号。不要太在意CSS和HTML代码,只需运行这段代码片段并使用它。但是,您可能希望了解与DOM无关的JavaScript代码(使用示例构造函数和垂直变量)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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 );
 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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;
}
1
2
3
4
5
6
7
<!--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></wyn>
<br />
<button id="run">Run</button>
<p id="result">...
</p>


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

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

!!a!(!a)相同。如果定义了aatrue!afalse!!atrue


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

因为javascript具有所谓的"真实"和"虚假"值,所以有些表达式在其他表达式中进行计算时,会导致出现真实或虚假条件,即使所检查的值或表达式实际上不是truefalse

例如:

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

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

然而:

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

…不会产生真实的条件,即使元素确实存在,也不会执行代码块。

为什么?因为document.getElementById()是一个"真实"的表达式,在这个if()语句中,它的计算结果为真,但它不是true的实际布尔值。

在这种情况下,两个"not"非常简单。它只是两个not背靠背。

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

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

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

两者都将按预期返回true。


双倍!将变量计算为其布尔值。Eg:假0(零)、""或""(空字符串)、空、未定义、NaN的计算结果为假。请参阅本帖https://www.sitepoint.com/javascript-truthy-falsy/


有时有必要检查我们在函数中是否有一个值,这个值本身对我们来说并不重要,但它是否重要。例如,我们想要检查,如果用户有或没有专业,并且我们有一个类似的函数:

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

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

就像这样:

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

还是一样

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

如果this.major有一个值,那么!this.major返回false,但是由于该值已经存在,我们需要返回true,所以我们使用!两次返回正确答案!(!this.major)


这是一种检查未定义"未定义"、空值"空值"、"未定义"的非常方便的方法。

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