我看到一些代码,似乎使用操作我不承认,在两个感叹号的形式,像这样:!!
。有人可以告诉我这个操作员是做什么的吗?
我看到这个的背景是,
this.vertical = vertical !== undefined ? !!vertical : this.vertical;
我看到一些代码,似乎使用操作我不承认,在两个感叹号的形式,像这样:!!
。有人可以告诉我这个操作员是做什么的吗?
我看到这个的背景是,
this.vertical = vertical !== undefined ? !!vertical : this.vertical;
转换Object
为boolean
. 如果它是假的(例如0
,null
,undefined
等),它将是false
,否则,true
。
!oObject // inverted boolean
!!oObject // non inverted boolean so true boolean representation
所以!!
不是运算符,它只是!
运算符两次。
真实世界示例“测试 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);
!!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!
泡茶:
!!
不是运营商。这是--的双重使用,!
这是逻辑“非”运算符。
理论上:
!
确定值不是什么的“真相”:
事实false
并非如此true
(这就是为什么会!false
导致true
)
事实true
并非如此false
(这就是为什么会!true
导致false
)
!!
确定一个值不是什么的“真相” :
事实true
并非如此 true
(这就是为什么会!!true
导致true
)
事实false
并非如此 false
(这就是为什么会!!false
导致false
)
我们希望在比较中确定的是关于引用值的“真相” ,而不是引用本身的值。有一个用例,我们可能想知道一个值的真实性,即使我们期望该值是false
(或假的),或者我们期望该值不是 typeof boolean
。
在实践中:
考虑一个简洁的函数,它通过动态类型(又名“鸭子类型”)检测特征功能(在这种情况下,是平台兼容性)。我们想编写一个函数,true
如果用户的浏览器支持 HTML5<audio>
元素,则返回该函数,但我们不希望该函数在<audio>
未定义时抛出错误;我们不想用来try ... catch
处理任何可能的错误(因为它们很糟糕);而且我们也不希望在函数内部使用检查,因为它不会始终如一地揭示有关该功能的真相(例如,即使不支持HTML5 ,document.createElement('audio')
仍将创建一个调用的元素)。<audio>
<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
每个函数都接受 a<tag>
和 an的参数以供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
从非布尔值、可能未定义的值中获取的最首选方法确实是使用!!
. 希望这可笑地清除它。
!!
将其右侧的值转换为其等效的布尔值。(想想穷人的“类型转换”方式)。它的意图是通常传达给读者,代码并不关心什么值是可变的,但它的“真”值是。