我看到一些代码似乎使用了一个我无法识别的运算符,以两个感叹号的形式出现,如下所示: !!
。有人可以告诉我这个运营商做了什么?
我看到这个的背景是,
this.vertical = vertical !== undefined ? !!vertical : this.vertical;
我看到一些代码似乎使用了一个我无法识别的运算符,以两个感叹号的形式出现,如下所示: !!
。有人可以告诉我这个运营商做了什么?
我看到这个的背景是,
this.vertical = vertical !== undefined ? !!vertical : this.vertical;
胁迫 oObject
到布尔值。如果它是假的(例如0, null
, undefined
等等),它会 false
, 除此以外, true
。
!oObject //Inverted boolean
!!oObject //Non inverted boolean so true boolean representation
所以 !!
不是运营商,只是运营商 !
操作员两次。
真实世界示例“测试IE版本”:
let isIE8 = false;
isIE8 = !! navigator.userAgent.match(/MSIE 8.0/);
console.log(isIE8); // returns true or false
如果你⇒
console.log(navigator.userAgent.match(/MSIE 8.0/));
// returns null
但如果你⇒
console.log(!!navigator.userAgent.match(/MSIE 8.0/));
// returns 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);
!!expr
返回一个布尔值(true
要么 false
)取决于 感实性 的表达。在非布尔类型上使用时更有意义。考虑这些示例,尤其是第3个示例及以后的示例:
!!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!
煮一些茶:
!!
不是运营商。它是两用的 !
- 这是逻辑“非”运算符。
理论上:
!
确定价值不是什么的“真相”:
事实是这样的 false
不是 true
(这就是为什么 !false
结果
在 true
)
事实是这样的 true
不是 false
(这就是为什么 !true
结果
在 false
)
!!
确定价值是什么的“真相” 不 不:
事实是这样的 true
不是 不 true
(这就是为什么 !!true
结果是 true
)
事实是这样的 false
不是 不 false
(这就是为什么 !!false
结果是 false
)
我们希望在比较中确定的是“真相” 关于 参考的价值,而不是 的价值 引用本身。有一个用例我们可能想知道一个值的真相,即使我们期望值是 false
(或假的),或者如果我们期望价值不是类型的话 boolean
。
在实践中:
考虑一个简洁的功能,通过它来检测功能功能(在这种情况下,平台兼容性) 动态打字 (又名“鸭子打字”)。我们想写一个返回的函数 true
如果用户的浏览器支持HTML5 <audio>
元素,但我们不希望函数抛出错误,如果 <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
寻找,但他们每个都根据比较确定的值返回不同的值。
但等等,还有更多!
你们中的一些人可能已经注意到,在这个具体的例子中,人们可以简单地使用稍微检查属性 性能更高 检查相关对象的方法 具有 财产。有两种方法可以做到这一点:
// 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
应用unary not运算符两次并用于转换为类似于使用unary plus的布尔类型 +foo
转换为数字并连接空字符串 ''+foo
转换为字符串。
您也可以使用与基元类型对应的构造函数来代替这些黑客攻击(无 运用 new
)明确地施放价值,即
Boolean(foo) === !!foo
Number(foo) === +foo
String(foo) === ''+foo
这么多答案做了一半的工作。是, !!X
可以被解读为“X的真实性[表示为布尔]”。但 !!
实际上,对于确定单个变量是否(或者即使许多变量是真实的)真实或虚假也是如此重要。 !!myVar === true
和刚刚一样 myVar
。对比 !!X
到“真正的”布尔值并不是真的有用。
你获得了什么 !!
能够检查多个变量的真实性 互相攻击 以可重复,标准化(和JSLint友好)的方式。
那是...
0 === false
是 false
。 !!0 === false
是 true
。以上不太有用。 if (!0)
给你相同的结果 if (!!0 === false)
。我想不出将变量转换为布尔值然后与“true”布尔值进行比较的好例子。
请参阅“==和!=” JSLint的指示 (注意:Crockford正在移动他的网站一点点;这个链接可能会在某个时候死掉),原因如下:
==和!=运算符在比较之前键入强制。这很糟糕,因为它会导致'\ t \ r \ n'== 0为真。这可以掩盖类型错误。 JSLint无法可靠地确定是否正确使用==,因此最好不要使用==和!=并始终使用更可靠的===和!==运算符。
如果您只关心某个值是真或假,那么请使用简短形式。代替
(foo != 0)
说啊
(foo)
而不是
(foo == 0)
说
(!foo)
请注意,有一些 不直观的案件 将布尔值强制转换为数字(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());
因为 一些历史的Windows jive,这将在消息框中输出-1!在cmd.exe提示符下尝试,看看!但 WScript.echo(-1 == test())
仍然给你0或WScript false
。 把目光移开这很可怕。
但是,如果我有两个值,我需要检查相同的truthi / falsi-ness?
假装我们有 myVar1 = 0;
和 myVar2 = undefined;
。
myVar1 === myVar2
是 0 === undefined
而且显然是假的。!!myVar1 === !!myVar2
是 !!0 === !!undefined
是真的!同样诚实! (在这种情况下,两者都“有真实性”。)因此,你真正需要使用“boolean-cast变量”的唯一地方是,如果你有一个情况,你要检查两个变量是否都有 相同 真实,对吧?那是, 使用 !!
如果你需要看看两个变量是什么 无论是真的还是两者都是假的 (或不),即 平等的 (或不) 感实性。
我无法想到一个伟大的,非人为的用例。也许你在表单中有“链接”字段?
if (!!customerInput.spouseName !== !!customerInput.spouseAge ) {
errorObjects.spouse = "Please either enter a valid name AND age "
+ "for your spouse or leave all spouse fields blank.";
}
所以现在,如果你有两个真正的truthy 要么 对于配偶姓名和年龄都是假的,你可以继续。否则你只有一个具有价值的领域(或者一个非常早期的婚姻),并且需要在你的领域产生额外的错误 errorObjects
采集。
编辑2017年10月24日:
这是一个有趣的案例...... !!
当第三方库期望显式布尔值时,可能会有用。
例如, JSX(React)中的False具有特殊含义 这不是简单的虚假引发的。如果您尝试在JSX中返回类似以下内容的内容,则需要使用int messageCount
...
{messageCount && <div>You have messages!</div>}
......你可能会惊讶地发现React渲染了一个 0
当你有零消息。您必须为JSX显式返回false才能呈现。上述声明返回 0
,JSX愉快地呈现,应该如此。它不能告诉你没有 Count: {messageCount && <div>Get your count to zero!</div>}
(或者不那么做作的东西)。
一个修复涉及强迫的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}
请记住 这个 是一个JSX约定,不是JavaScript固有的。
但如果你看到奇怪的话 0
在你渲染的JSX中,考虑松散的虚假管理。
它只是逻辑NOT运算符,两次 - 它用于将某些东西转换为布尔值,例如:
true === !!10
false === !!0
它将后缀转换为布尔值。
这是双倍的 not
操作。首先 !
将值转换为布尔值并反转其逻辑值。第二 !
将逻辑值反转回来。
它模拟了行为 Boolean()
铸造功能。
首先 NOT
无论给出什么操作数,都返回一个布尔值。第二 NOT
否定这一点 Boolean
价值等等给出了 true
变量的布尔值。最终结果与使用相同 Boolean()
函数值。