javascript - JavaScript 中!! 操作符是什么?

  显示原文与译文双语对照的内容

我看到一些代码似乎使用了一个运算符,我无法识别它们,但它们的形式是两个感叹号,如下所示: 。有人能告诉我这个操作符做什么?!

我看到的上下文是


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

时间:

oObject 强制为布尔值。如果它是 falsey ( 例如。 0,nullundefined,等等 ),它将是 false,否则,true


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

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

这是一种非常晦涩的方式来进行类型转换。

是 。! 所以 truefalsefalsetrue 。! 0true1false 。!

所以你将一个值转换为布尔值,然后反转它,然后再反转一次。


//Maximum Obscurity:
val.enabled =!!userId;

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

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

!!expr把任何 truthy 表达式转化为布尔 true ( 和 false 否则) 返回布尔值( true 或者 false ),具体取决于表达式的truthiness 。 在non-boolean类型上使用时更有意义。 考虑以下示例,特别是 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!

将它的右侧的值转换为它的等效的布尔值。! ( 思考"type-casting"的糟糕方法) 。 它的意图是通常的传达给读者某些代码不关心 什么值是在变量中,但它是什么 "真值"值是。

泡茶茶:

不是运算符。! 它是的double-use --哪个是逻辑"δ"运算符。!


理论上

确定值不是值的"真值":!

  • true ), false 事实是,不是 true ( 这就是为什么 false 结果!

  • false ), true 事实是,不是 false ( 这就是为什么 true 结果!


决定了一个值是不不是什么:"真值"。!

  • true ), true的事实是域控制器不是 true ( 这就是为什么 true 结果!

  • false ), false的事实是域控制器不是 false ( 这就是为什么 false 结果!


我们希望在比较中确定的是该"真值"关于,而非值的引用,该引用的值本身。 这里有一个 use-case,我们可能想要知道一个值的事实,即使我们期望这个值是 false ( 或者 falsey ),或者如果我们期望该值不是 boolean


实践中的

考虑这样一个简洁的功能,被用来检测特征功能( 在这种情况下,平台兼容性) 通过方式 动态类型 ( aka"鸭子类型") 。 我们要编写一个函数,返回 true 如果用户的浏览器支持了 html 5,但我们不希望在函数以抛出错误如果 <audio><audio> 元素未定义) ;我们不想使用 try.. . catch 也来处理任何可能的错误( 因为它们是粗糙的) ;和我们不想使用一个调查有关这里功能的函数,该函数将不一致地揭示实际的情况里面该( 例如创建一个元素称为 <audio> 即使 html 5 不支持 <audio>document.createElement('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

我们跑题- -

使用然而少见这些情况下的效率,可能存在少数有些情况,最简洁,最可执行的,因此最首选的方法来获得从一个 non-boolean,可能是未定义的值确实为 true by. 希望这把它彻底清除。

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

你还可以使用与基元类型( 使用无 ) 相对应的构造函数函数来显式转换值,IE


Boolean(foo) ===!!foo
Number(foo) === +foo
String(foo) === ''+foo

它只是逻辑非运算符两次- 它被用来将某些东西转换成布尔值,e.g.:


true ===!!10

false ===!!0

它将后缀转换为布尔值。

它模拟 Boolean() 转换函数的行为。 第一个 NOT 返回一个布尔值不管它是什么操作数。 第二个 NOTBoolean 值求反,因此给出变量的true 布尔值。 最终结果与在值上使用 Boolean() 函数相同。

这是一个双重 not 操作。 第一个 将该值转换为布尔值并反转它的逻辑值。! 第二个 将逻辑值反向。!

...