我看到一些代码似乎使用了我不认识的运算符,以两个感叹号的形式,像这样:!!。有人能告诉我这个接线员做什么吗?

我看到这件事的背景是,

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

当前回答

JavaScript中的一些运算符执行隐式类型转换,有时用于类型转换。

一元!运算符将其操作数转换为布尔值并对其求反。

这一事实导致了以下习惯用法,您可以在源代码中看到:

!!x // Same as Boolean(x). Note double exclamation mark

其他回答

!!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!

!!foo两次应用一元not运算符,并用于转换为布尔类型,类似于使用一元加号+foo转换为数字,并连接空字符串“”+foo以转换为字符串。

除了这些黑客,您还可以使用与基元类型相对应的构造函数(不使用new)来显式转换值,即。,

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

if和while语句以及?运算符使用真值来确定要运行的代码分支。例如,零和NaN数字以及空字符串为假,但其他数字和字符串为真。对象为true,但未定义的值和null均为false。

双重否定运算符!!计算值的真值。实际上是两个操作员,哪里!!x表示!(!x),并且行为如下:

如果x为假值!x为真,并且!!x为假。如果x是真值!x为假,并且!!x为真。

当在布尔上下文的顶层使用时(if、while或?)!!从行为上讲,操作员是一个no-op。例如,if(x)和if(!!x)表示相同的意思。

实际用途

然而,它有几个实际用途。

一种用法是将对象压缩到其真值,这样代码就不会保存对大对象的引用并保持其活动。分配!!some_big_object设置为变量,而不是some_biguobject让垃圾收集器使用它。这对于生成对象或假值(例如空值或未定义值)的情况非常有用,例如浏览器特征检测。

另一个用法,我在一个关于C对应的答案中提到了!!操作员使用“lint”工具查找常见的打字错误和打印诊断。例如,在C和JavaScript中,布尔运算的一些常见错误会产生其他输出不太布尔的行为:

如果(a=b)是赋值,然后使用b的真值;如果(a==b)是相等比较。如果(a&b)是位AND;如果(a&&b)是逻辑AND。2和5为0(假值);2&&5为真。

这个操作员向lint工具保证,您所写的就是您的意思:执行此操作,然后获取结果的真值。

第三种用途是产生逻辑XOR和逻辑XNOR。在C和JavaScript中,a&b都执行逻辑and(如果两边都为true,则为true),a&b执行逐位and。a||b执行逻辑或(如果至少有一个为真,则为真),a|b执行逐位或。有一个按位XOR(异或)作为^b,但没有用于逻辑XOR的内置运算符(如果只有一侧为真,则为真)。例如,您可能希望允许用户仅在两个字段中的一个字段中输入文本。您可以做的是将每个值转换为一个真值,并将它们进行比较:!!x!==!!y

这是一次双重手术。第一个!将值转换为布尔值并反转其逻辑值。第二个!反转逻辑值。

我认为值得一提的是,与逻辑“与/或”组合的条件不会返回布尔值,而是在&&的情况下返回最后一次成功或第一次失败,在条件链的||的情况下,返回第一次成功或最后一次失败。

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