是什么 !!(不是)JavaScript 中的运算符?

IT技术 javascript operators
2021-01-14 10:32:05

我看到一些代码,似乎使用操作我不承认,在两个感叹号的形式,像这样:!!有人可以告诉我这个操作员是做什么的吗?

我看到这个的背景是,

this.vertical = vertical !== undefined ? !!vertical : this.vertical;
6个回答

转换Objectboolean. 如果它是假的(例如0nullundefined等),它将是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
它将非布尔值转换为反转的布尔值(例如,!5 将是假的,因为 5 是 JS 中的非假值),然后布尔值反转,因此您将原始值作为布尔值(所以 !!5 将是真的)。
2021-03-14 10:32:05
@Micah Snyder 请注意,在 JavaScript 中最好使用布尔基元,而不是创建使用 new Boolean() 装箱布尔值的对象。这是一个查看差异的示例:jsfiddle.net/eekbu
2021-03-23 10:32:05
据我所知,这种 bang-bang 模式在 if(…_ 语句;仅在应该返回布尔值的函数的 return 语句中没有用。
2021-03-23 10:32:05
一个简单的描述方法是:Boolean(5) === !!5; 相同的演员阵容,更少的角色。
2021-03-25 10:32:05
这用于将真值转换为布尔值真,假值太布尔假。
2021-04-05 10:32:05

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

!不是所以!truefalse!falsetrue!0true,并且!1false

因此,您将一个值转换为布尔值,然后将其反转,然后再次反转。

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

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

// And finally, much easier to understand:
val.enabled = (userId != 0);
我的大脑在解码!!varBoolean(var).. 时没有任何问题,!!并且比替代方案更快(处理指令更少)和更短。
2021-03-17 10:32:05
我知道你多年前写过这个答案,但为了今天的改进:最容易理解的是说出你的意思Boolean(x)我认为您的任何替代方案都不容易理解。更糟糕的是,至少在一种情况下,使用相等运算符x != 0会给出与Boolean(x)or不同的结果!!x:try []for x。此外,如果您确实喜欢使用相等运算符,以获取其“真实性”规则,为什么不做更明显的(userId == true)而不是(userId != 0)?
2021-03-22 10:32:05
!!false是假的。false != 0是真的。所以它们不是等价的。!!用于将任何内容强制为布尔值的有用目的
2021-03-28 10:32:05
“更容易理解”的变体在这里真的更容易理解吗?对 0 的检查并不是对 0 的实际检查,而是对 Javascript 认为等于 0 的有点奇怪的值列表的检查。 userId ? true : false 更清楚地表明正在进行转换并处理 userId 的值可能已显式设置为的情况undefined
2021-04-11 10:32:05
!!假=假。!!真=真
2021-04-12 10:32:05

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

          !!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!
@SalmanA 扩展到您的正确评论!!(new Boolean(false).valueOf()) // false(因为 new Boolean 返回一个布尔对象的实例,它是真实的,而 Boolean(false) 或 Boolean valueOf() 将表达式的值强制为原始布尔值)。
2021-03-19 10:32:05
添加!!undefined //false 到这个很棒的答案的明确建议
2021-03-28 10:32:05
...但是也 !!Boolean(false) // false
2021-04-06 10:32:05
值得注意: !!new Boolean(false) // true
2021-04-10 10:32:05
new Boolean(false) 是一个对象,一个对象即使包含一个假值也是真值!
2021-04-12 10:32:05

泡茶:

!!不是运营商。这是--的双重使用,!这是逻辑“非”运算符。


理论上:

! 确定值不是什么的“真相”:

  • 事实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从非布尔值、可能未定义的值中获取的最首选方法确实是使用!!. 希望这可笑地清除它。

完全很棒的答案,但我看不到它的实用性!!构造。由于if()语句已经将表达式转换为布尔值,因此将测试函数的返回值显式转换为布尔值是多余的 - 因为就if()语句而言,“真实性” === 真或者我错过了一个场景,你需要一个真实的表达式来实际是布尔值true
2021-03-27 10:32:05
@TomAugerif()语句确实对 falsey 值进行了布尔值转换,但是假设您想在对象上实际设置一个布尔值标志 - 它不会像if()语句那样进行转换。例如,object.hasTheThing = !!castTheReturnValToBoolNoMatterWhat()将设置truefalse代替实际返回值。另一个例子是,也许所有的管理员都id0和非管理员的ID1或更高。要获得true,如果有人不是你可以做管理员person.isNotAdmin = !!admin.id用例很少,但有的时候很简洁。
2021-04-09 10:32:05

!!将其右侧的值转换为其等效的布尔值。(想想穷人的“类型转换”方式)。它的意图是通常传达给读者,代码并不关心什么值是可变的,但它的“真”值是。

重点是您可能不知道其内容的变量;如果它可以是整数或字符串、对象或空值、未定义等。这是一种测试存在性的简单方法。
2021-03-21 10:32:05
或者在右侧的布尔值的情况下,它什么也不做。
2021-03-24 10:32:05
但重点是什么?如果我做if(0){...Javascript 已经知道这是错误的。为什么说更好if(!!0){...
2021-03-29 10:32:05
@Daniel:!仍然将值向右翻转。在布尔值的情况下,最右边的!否定该值,而最左边的!则再次否定它。净效果是没有变化,但大多数引擎会为双重否定生成操作码。
2021-04-04 10:32:05