我看到一些代码似乎使用了我不认识的运算符,以两个感叹号的形式出现,例如:!!
。有人可以告诉我这个操作员是做什么的吗?
我看到这个的背景是,
this.vertical = vertical !== undefined ? !!vertical : this.vertical;
if(vertical !== undefined) this.vertical = Boolean(vertical);
- 正在发生的事情更加清晰和清晰,不需要不必要的分配,完全是标准的,并且同样快(在当前的 FF 和 Chrome 上)jsperf.com/boolean-conversion-speed。
!!5/0
产生 Infinity
而不是 true
产生的原因,如 Boolean(5/0)
产生的。 !!5/0
等价于 (!!5)/0
(也称为 true/0
),因为 !
运算符的优先级高于 /
运算符。如果您想使用双键布尔化 5/0
,则需要使用 !!(5/0)
。
将 Object
转换为 boolean
。如果它是假的(例如 0
、null
、undefined
等),则为 false
,否则为 true
。
!object // inverted boolean
!!object // non inverted 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
这是进行类型转换的一种非常晦涩的方法。
!
表示不。所以 !true
是 false
,而 !false
是 true
。 !0
是 true
,!1
是 false
。
因此,您将一个值转换为布尔值,然后将其反转,然后再次反转它。
// 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);
注意:后两个表达式在某些极端情况(例如,当 userId
为 []
时)并不完全等同于第一个表达式,因为 {3 } 运算符有效,什么值被认为是 truthy。
userId ? true : false
更清楚地表明正在进行转换并处理 userId 的值可能已经存在的情况明确设置为 undefined
!!var
解码为 Boolean(var)
.. 并且 !!
比其他方法更快(处理指令更少)且更短。
!!false
为假。 false != 0
为真。所以它们不是等价的。 !!
用于将 anything 强制为布尔值。
Boolean(x)
。我认为您的任何替代方案都不容易理解。更糟糕的是,至少在一种情况下,使用相等运算符 x != 0
会得到与 Boolean(x)
或 !!x
不同的结果:尝试 []
for x。此外,如果您确实喜欢使用等式运算符来获得其“真实性”规则,那么您为什么不使用更明显的 (userId == true)
而不是 (userId != 0)
呢?
!!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!
!!new Boolean(false) // true
!!Boolean(false) // false
new Boolean(false)
是一个对象,一个对象是真的,即使它包含一个假值!
!!undefined //false
添加到这个出色的答案中!
!!(new Boolean(false).valueOf()) // false
(因为 new Boolean 返回一个 Boolean 对象的实例,这是真实的,而 Boolean(false) 或 Boolean valueOf() 将表达式的值强制为原始布尔值)。
泡茶:
!!
不是运算符。它是 !
的双重用途——它是逻辑“非”运算符。
理论上:
!
确定值不是什么的“真相”:
事实是假不是真的(这就是为什么!假结果为真)
事实是 true 不是 false(这就是为什么 !true 结果为 false)
!!
确定一个值的“真相”not not:
事实是 true 不是 true (这就是为什么 !!true 结果为 true)
事实是假不是不假(这就是为什么!!假导致假)
我们希望在比较中确定的是关于引用值的“真相”,而不是引用本身的值。有一个用例,我们可能想知道一个值的真相,即使我们期望该值是 false
(或错误),或者如果我们期望该值不是boolean
类型。
在实践中:
考虑一个简洁的函数,它通过 dynamic typing(又名“duck typing”)检测特性功能(在本例中为平台兼容性)。如果用户的浏览器支持 HTML5 <audio>
元素,我们希望编写一个返回 true
的函数,但如果 <audio>
未定义,我们不希望该函数抛出错误;而且我们不想使用 try ... catch
来处理任何可能的错误(因为它们很严重); 而且我们不希望在函数内部使用检查不能始终如一地揭示特性的真相(例如,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>
和 attribute
的参数,但它们各自根据比较确定的内容返回不同的值。
但是等等,还有更多!
你们中的一些人可能已经注意到,在这个特定的示例中,人们可以简单地使用略为 more performant 的方法来检查所讨论的对象是否具有属性。有两种方法可以做到这一点:
// 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
的方法确实是使用 !!
。希望这可笑地清除它。
if()
语句已经将表达式转换为布尔值,因此将测试函数的返回值显式转换为布尔值是多余的 - 因为无论如何“真实性” === true 就 if()
语句而言。还是我错过了一个你需要一个真实的表达式才能真正成为布尔 true
的场景?
if()
语句确实针对虚假值强制转换布尔值,但是说您想在对象上实际设置一个布尔标志 - 它不会像 if()
语句那样强制转换它。例如 object.hasTheThing = !!castTheReturnValToBoolNoMatterWhat()
将设置 true
或 false
而不是真正的返回值。另一个示例可能是所有管理员都是 0
的 id
,而非管理员的 id 为 1
或更高。如果某人不是管理员,要获得 true
,您可以执行 person.isNotAdmin = !!admin.id
。用例很少,但有的时候很简洁。
!!
将其右侧的值转换为其等效的布尔值。 (想想穷人的“类型转换”方式)。它的意图通常是为了向读者传达代码并不关心变量中的值是什么,而是它的"truth" value是什么。
!
仍然将值翻转到右侧。在布尔值的情况下,最右边的 !
否定该值,而最左边的 !
再次否定它。净效果是没有变化,但大多数引擎会为双重否定生成操作码。
if(0){...
Javascript 已经知道这是错误的。为什么说if(!!0){...
更好?
!!foo
应用一元非运算符两次,用于转换为布尔类型,类似于使用一元加 +foo
转换为数字并连接空字符串 ''+foo
以转换为字符串。
除了这些技巧,您还可以使用与原始类型对应的构造函数(without using new
)显式转换值,即
Boolean(foo) === !!foo
Number(foo) === +foo
String(foo) === ''+foo
new
的情况下调用构造函数-正如我的回答中明确提到的
x="0"
只需执行:x=!!+x; //false
与 Boolean(Number(x))
相同 Number(或 +x)将字符串“0”转换为 0,它的评估结果为假,然后布尔 (!!x) 直接将其转换为布尔值。十分简单!
!!+x
和 x !== "0"
?
这么多答案做了一半的工作。是的,!!X
可以理解为“X [表示为布尔值] 的真实性”。但实际上,!!
对于确定单个变量是(或者即使许多变量是)真还是假并不是那么重要。 !!myVar === true
与 myVar
相同。将 !!X
与“真正的”布尔值进行比较并不是很有用。
您使用 !!
获得的唯一好处是能够以可重复、标准化(且 JSLint 友好)的方式检查多个变量的真实性相互。
简单地铸造:(
那是...
0 === 假是假的。
!!0 === 假是真的。
上面的用处不大。 if (!0)
为您提供与 if (!!0 === false)
相同的结果。我想不出将变量转换为布尔值然后与“真实”布尔值进行比较的好案例。
请参阅 JSLint's directions 中的“== 和 !=”(注意:Crockford 正在稍微移动他的网站;该链接可能会在某个时候失效)以了解原因:
== 和 != 运算符在比较之前进行强制类型转换。这很糟糕,因为它会导致 ' \t\r\n' == 0 为真。这可以掩盖类型错误。 JSLint 无法可靠地确定 == 是否被正确使用,因此最好不要使用 == 和 != 并始终使用更可靠的 === 和 !== 运算符。如果你只关心一个值是真还是假,那么使用简写形式。而不是 (foo != 0) 只是说 (foo) 而不是 (foo == 0) 说 (!foo)
请注意,在将布尔值与数字进行比较时,有些 unintuitive cases 会将布尔值转换为数字(true
转换为 1
,false
转换为 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());
由于 some historical Windows jive,这将在消息框中输出 -1!在 cmd.exe 提示符下试试看!但是 WScript.echo(-1 == test())
仍然给你 0,或者 WScript 的 false
。 Look away. It's hideous.
比较真实性:)
但是,如果我有两个值需要检查相等的真/假怎么办?
假设我们有 myVar1 = 0;
和 myVar2 = undefined;
。
myVar1 === myVar2 为 0 === 未定义,显然是错误的。
!!myVar1 === !!myVar2 是 !!0 === !!undefined 并且是真的!一样的真实! (在这种情况下,两者都“具有虚假的真实性”。)
因此,您真正需要使用“布尔转换变量”的唯一地方是,您需要检查两个变量是否具有 same 真实性,对吗?也就是说,如果您需要查看两个变量是否都为真或都为假(或不是),则使用!!
,即相等(或不)真实性。
我想不出一个伟大的、非人为的用例来做这个副手。也许您在表单中有“链接”字段?
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 方库需要明确的布尔值时,!!
可能很有用。
反应
例如,False in JSX (React) has a special meaning 不会因简单的虚假而触发。如果您尝试在 JSX 中返回类似以下内容,则期望 messageCount
中为 int ...
{messageCount && <div>You have messages!</div>}
...当您的消息为零时,您可能会惊讶地看到 React 呈现 0
。您必须显式返回 false 才能使 JSX 不呈现。上面的语句返回 0
,JSX 会按照它应该的方式愉快地渲染它。它不能告诉您没有 Count: {messageCount}
。
一种修复方法是使用 bangbang,它将 0 强制转换为 !!0,这是错误的:{!!messageCount &&
JSX 的文档建议您更加明确,编写自注释代码,并使用比较来强制为布尔值。 {messageCount > 0 &&
我更愿意自己用三元处理虚假 - {messageCount ?
打字稿
Typescript 中的相同处理:如果您有一个返回布尔值的函数(或者您正在为布尔变量分配一个值),那么您 [通常] 不能返回/分配一个 boolean-y 值;它必须是强类型的布尔值。这意味着,如果 myObject
是强类型,return !myObject;
适用于返回布尔值的函数,但 return myObject;
不适用。您必须 return !!myObject
(或以另一种方式转换为正确的布尔值)才能匹配 Typescript 的期望。
Typescript 的例外?如果 myObject 是 any,那么您就回到了 JavaScript 的狂野西部并且可以在没有 !! 的情况下返回它,即使您的返回类型是布尔值。
请记住,这些是 JSX 和 Typescript 约定,而不是 JavaScript 固有的约定。
但是,如果您在渲染的 JSX 中看到奇怪的 0
,请考虑松散的虚假管理。
if (!!window.Worker)
true
“外部”在 if
中的操作完全相同。我一直在尝试,但我想不出有什么理由更喜欢将真实性转换为布尔值,而不是上面那种令人费解的“比较真实性”案例,除非您稍后重用该值时的可读性,如 {3 } 库示例。但即便如此,这也是一条信息丢失的捷径,我认为你最好每次都评估真实性。
它只是逻辑 NOT 运算符,两次 - 它用于将某些内容转换为布尔值,例如:
true === !!10
false === !!0
它将后缀转换为布尔值。
这是一个双 not
操作。第一个 !
将值转换为布尔值并反转其逻辑值。第二个 !
反转逻辑值。
似乎 !!
运算符导致双重否定。
var foo = "Hello World!";
!foo // Result: false
!!foo // Result: true
它模拟 Boolean()
转换函数的行为。无论给出什么操作数,第一个 NOT
都会返回一个布尔值。第二个 NOT
否定 Boolean
值,因此给出变量的 true
布尔值。最终结果与对值使用 Boolean()
函数相同。
!!
它同时使用了 NOT
操作两次,!
将值转换为 boolean
并将其反转,因此使用它两次,显示该值的布尔值(false 或 true)。下面是一个简单的例子,看看 !!
是如何工作的:
首先,你有的地方:
var zero = 0;
然后你做!0
,它将被转换为布尔值并被评估为true
,因为0是falsy
,所以你得到反转的值并转换为布尔值,所以它被评估为true
。
!zero; //true
但是我们不想要值的反转布尔版本,所以我们可以再次反转它来得到我们的结果!这就是我们使用另一个 !
的原因。
基本上,!!
确保我们得到的值是布尔值,而不是假值、真值或字符串等......
所以这就像在 javascript 中使用 Boolean
函数,但是将值转换为布尔值的简单且更短的方法:
var zero = 0;
!!zero; //false
!是“布尔非”,它本质上将“启用”的值类型转换为其布尔值的对立面。第二 !翻转这个值。因此,!!enable
表示“未启用”,将 enable
的值作为布尔值提供给您。
我认为值得一提的是,与逻辑 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
!!
构造是一种将任何 JavaScript 表达式转换为其等效布尔值的简单方法。
例如:!!"he shot me down" === true
和 !!0 === false
。
0 === false
为假,!!0 === false
为真。
这不是一个操作员,而是两个。它等效于以下内容,是一种将值转换为布尔值的快速方法。
val.enabled = !(!enable);
这个问题已经得到了相当彻底的回答,但我想添加一个我希望尽可能简化的答案,使 !!尽可能简单地掌握。
因为 javascript 具有所谓的“真”和“假”值,所以有些表达式在其他表达式中求值时会产生真或假条件,即使正在检查的值或表达式实际上不是 true
或 {2 }。
例如:
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。
我怀疑这是 C++ 的遗留物,人们会覆盖 !运算符,但不是布尔运算符。
因此,在这种情况下,要获得否定(或肯定)答案,您首先需要使用 !运算符获取布尔值,但如果您想检查肯定的情况,请使用 !!。
if
和 while
语句以及 ?
运算符使用真值来确定要运行的代码分支。例如,零和 NaN 数字和空字符串为假,但其他数字和字符串为真。对象为真,但未定义值和 null
均为假。
双重否定运算符 !!
计算一个值的真值。它实际上是两个运算符,其中 !!x
表示 !(!x)
,其行为如下:
如果 x 为假值,则 !x 为真,而 !!x 为假。
如果 x 为真值,!x 为假,!!x 为真。
在布尔上下文(if
、while
或 ?
)的顶层使用时,!!
运算符在行为上是无操作的。例如,if (x)
和 if (!!x)
表示相同的意思。
实际用途
然而,它有几个实际用途。
一种用途是将对象有损地压缩为其真值,这样您的代码就不会持有对大对象的引用并使其保持活动状态。将 !!some_big_object
分配给变量而不是 some_big_object
可以让垃圾收集器放弃它。这对于生成对象或错误值(例如 null
)或未定义值(例如浏览器功能检测)的情况很有用。
我在 answer about C's corresponding !!
operator 中提到的另一个用途是使用“lint”工具来查找常见的拼写错误和打印诊断。例如,在 C 和 JavaScript 中,布尔运算的一些常见拼写错误会产生其他行为,其输出与布尔运算不同:
if (a = b) 是赋值,然后使用 b 的真值; if (a == b) 是相等比较。
if (a & b) 是按位与; if (a && b) 是逻辑与。 2 & 5 为 0(假值); 2 && 5 为真。
!!
运算符向 lint 工具保证您所写的就是您的意思:执行此操作,然后取结果的真值。
第三种用途是产生逻辑 XOR 和逻辑 XNOR。在 C 和 JavaScript 中,a && b
执行逻辑与(如果双方都为真,则为真),a & b
执行按位与。 a || b
执行逻辑 OR(如果至少有一个为真,则为真),而 a | b
执行按位 OR。 a ^ b
有一个按位 XOR(异或),但没有用于逻辑 XOR 的内置运算符(如果恰好一侧为真,则为真)。例如,您可能希望允许用户在两个字段之一中输入文本。您可以做的是将每个转换为真值并进行比较:!!x !== !!y
。
双布尔否定。通常用于检查值是否未定义。
我只是想补充一点
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
这里的技巧是 &&
链将返回它找到的 第一个错误值 - 这可以提供给 if 语句等。所以如果 b.foo 未定义,它将返回undefined 并跳过 b.foo.bar
语句,我们不会得到任何错误。
上面的返回 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
相同。
({}).anything
会给 undefined
!!x
是 Boolean(x)
的简写
第一个 bang 强制 js 引擎运行 Boolean(x)
但也有反转值的副作用。所以第二次爆炸消除了副作用。
它强制所有东西都是布尔值。
例如:
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
这里有很多很好的答案,但如果你已经读到这里,这有助于我“明白”。在 Chrome(等)上打开控制台,然后开始输入:
!(!(1))
!(!(0))
!(!('truthy'))
!(!(null))
!(!(''))
!(!(undefined))
!(!(new Object())
!(!({}))
woo = 'hoo'
!(!(woo))
...etc, etc, until the light goes on ;)
当然,这些都与仅键入 !!someThing 相同,但添加的括号可能有助于使其更易于理解。
在看到所有这些很棒的答案之后,我想添加另一个使用 !!
的原因。目前我正在使用 Angular 2-4 (TypeScript),当我的用户未通过身份验证时,我想返回一个布尔值作为 false
。如果他未通过身份验证,则令牌字符串将为 null
或 ""
。我可以通过使用下一个代码块来做到这一点:
public isAuthenticated(): boolean {
return !!this.getToken();
}
这是来自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 将是真的,而且还有一个!这将是错误的
返回变量的布尔值。
相反,可以使用 Boolean
类。
(请阅读代码说明)
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
正在使用中。
请查看下面的代码片段↓
let a = 0 console.log("a: ", a) // 将值写入其类型 console.log("!a: ", !a) // 将 '0 is NOT true in boolean' 写入 boolean - 这是真的。在布尔值中,0 表示假,1 表示真。 console.log("!!a: ", !!a) // 在布尔值中写入 0 值。 0 表示错误。 console.log("Boolean(a): ", Boolean(a)) // 等于 `!!a` console.log("\n") // 换行 a = 1 console.log("a: ", a) console.log("!a: ", !a) console.log("!!a: ", !!a) // 在布尔值中写入 1 个值 console.log("\n") // 换行 a = "" console.log("a: ", a) console.log("!a: ", !a) // 写 '"" is NOT true in boolean' value as boolean - 所以这是真的。在 boolean empty字符串、空值和未定义值表示假,如果有字符串则表示真。 console.log("!!a: ", !!a) // 将 "" 值写入布尔值 console.log("\n") // 换行 a = "test" console.log("a: ", a ) // 在其类型中写入一个值 console.log("!a: ", !a) console.log("!!a: ", !!a) // 在布尔值中写入“测试”值 console.log( "Boolean(a) === !!a: ", Boolean(a) === !!a) // 写成 true
使用逻辑非运算符两次
表示 !true = false
和 !!true = true
请务必记住 JavaScript 中对 true
和 false
的计算:
带有“值”的所有内容都是真的(即真),例如:101、3.1415、-11、“幸运脑”、new Object(),当然还有真的
101,
3.1415,
-11,
“幸运大脑”,
新对象()
而且,当然,真的
没有“值”的所有内容都是假的(即假的),例如:0、-0、“”(空字符串)、未定义、空、NaN(不是数字),当然还有假
0,
-0,
"" (空字符串),
不明确的,
无效的,
NaN(不是数字)
当然,错误的
应用“logical not”运算符 (!
) 计算操作数,将其转换为 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
价值2 =价值;分配确切的对象值,即使它不是布尔值,因此 value2 不一定最终是布尔值。
价值2 = !!价值;作为操作数值的双重否定的结果,分配一个有保证的布尔值,它等价于以下但更短且可读性:
如果(值){ value2 = true; } 其他 { value2 = false; }
===
或 !==
运算符,以及在幕后发生的隐藏转换操作,我在我提供的例子。