关于javascript:如何!!?(不是不是波浪形/爆炸声波)改变’包含/包含’数组方法调用的结果?

How does !!~ (not not tilde/bang bang tilde) alter the result of a 'contains/included' Array method call?

如果您阅读jquery inArray页面上的评论,这里有一个有趣的声明:

1
!!~jQuery.inArray(elm, arr)

现在,我相信一个双感叹号会将结果转换为类型boolean,值为true。我不明白的是tilde(~操作符)在所有这些操作中的用途是什么?

1
2
var arr = ["one","two","three"];
if (jQuery.inArray("one", arr) > -1) { alert("Found"); }

重构if语句:

1
if (!!~jQuery.inArray("one", arr)) { alert("Found"); }

击穿:

1
2
3
4
jQuery.inArray("one", arr)     // 0
~jQuery.inArray("one", arr)    // -1 (why?)
!~jQuery.inArray("one", arr)   // false
!!~jQuery.inArray("one", arr)  // true

我还注意到,如果我把tilde放在前面,结果是-2

1
~!!~jQuery.inArray("one", arr) // -2

我不明白这里的瓷砖的用途。有人能解释一下吗?或者给我指一个资源?


有时你会看到~$.inArray前面应用,这是一个特殊的原因。

基本上,

1
~$.inArray("foo", bar)

是一个较短的方法

1
$.inArray("foo", bar) !== -1

如果找到第一个参数,$.inArray返回数组中项目的索引;如果找不到参数,则返回-1。这意味着,如果要查找布尔值"数组中是否有此值?",不能进行布尔比较,因为-1是一个真正的值,当$.in array返回0(一个错误的值)时,它意味着它实际上是在数组的第一个元素中找到的。

应用~位运算符使-1变为0,使0变为`-1。因此,不在数组中查找值并应用按位非将导致错误值(0),所有其他值都将返回非0数字,并表示真实的结果。

1
2
3
if (~$.inArray("foo", ["foo",2,3])) {
    // Will run
}

它会按预期工作。


expr-1true时,!!~expr评价为false。与expr != -1相同,只是坏了*

它的工作是因为javascript按位操作将操作数转换为2的补码格式的32位有符号整数。因此,!!~-1的评价如下:

1
2
3
4
   -1 = 1111 1111 1111 1111 1111 1111 1111 1111b // two's complement representation of -1
  ~-1 = 0000 0000 0000 0000 0000 0000 0000 0000b // ~ is bitwise not (invert all bits)
   !0 = true                                     // ! is logical not (true for falsy)
!true = false                                    // duh

-1以外的值将至少有一个位设置为零;反转该值将创建一个Truthy值;将!运算符两次应用于Truthy值将返回布尔值true。

当与.indexOf()一起使用时,我们只想检查结果是否为-1

1
2
3
!!~"abc".indexOf("d") // indexOf() returns -1, the expression evaluates to false
!!~"abc".indexOf("a") // indexOf() returns  0, the expression evaluates to true
!!~"abc".indexOf("b") // indexOf() returns  1, the expression evaluates to true

*!!~8589934591的计算结果为false,因此此abointenance不能可靠地用于测试-1


tilde操作符实际上根本不是jquery的一部分,它本身就是一个按位非操作符。

看到蒂尔德(~)的伟大神秘。

你在实验中得到了奇怪的数字,因为你正在对一个整数执行一个位逻辑运算(据我所知,它可能被存储为二的补码或类似的东西…)

二的补码解释了如何用二进制表示数字。我想我是对的。


~foo.indexOf(bar)是表示foo.contains(bar)的常用缩写,因为contains函数不存在。

由于javascript的"错误"值概念,通常不需要强制转换为布尔值。在这种情况下,它用于强制函数的输出为truefalse


jQuery.inArray()返回-1表示"未找到",其补码(~0。因此,~jQuery.inArray()返回falsy值(0表示"未找到",返回truthy值(负整数)表示"已找到"。然后,!!将falsy/truthy形式化为真正的布尔型false/true。因此,!!~jQuery.inArray()将给予true表示"已发现",false表示"未发现"。


所有4个字节的~与该公式-(N+1)相等。

所以

1
2
3
~0   = -(0+1)   // -1
~35  = -(35+1)  // -36
~-35 = -(-35+1) //34


tilde不是按位的-它反转值的每一位。一般的经验法则是,如果对一个数字使用~,它的符号将被颠倒,然后1将被减去。

因此,当您执行~0操作时,您得到-1(0反转为-0,减去1为-1)。

它本质上是一种精心设计的、超微观优化的获取值的方法,这种值总是布尔值。


~运算符是位补码运算符。当找不到元素时,inArray()的整数结果是-1,或者是一些非负整数。-1的按位补码(二进制表示为所有1位)为零。任何非负整数的位补总是非零的。

因此,当整数"i"为非负整数时,!!~i将是true,当"i"为-1时,false将是true

注意,~总是将其操作数强制为整数;也就是说,它强制非整数浮点值为整数,也强制非数值。


你说得对:当indexOf调用返回-1时,此代码将返回false;否则返回true

如你所说,使用

1
return this.modifiedPaths.indexOf(path) !== -1;


~运算符是位非运算符。这意味着它需要一个二进制形式的数字,把所有的0变成1,把1变成0。

例如,二进制中的数字0是0000000,而-1是11111111。同样,1是二进制的00000001,而-2是11111110


我的猜测是,它之所以存在,是因为它短了几个字符(图书馆的作者总是在追求)。它还使用在编译为本机代码时只需要几个机器周期的操作(而不是与数字进行比较)。

我同意另一个答案,即这是一个过度杀伤力,但可能在一个紧密的循环中是有意义的(尽管需要性能增益估计,否则可能是过早的优化)。


我假设,因为它是一个位操作,所以它是检查路径是否出现在modifiedpaths中的最快(计算成本较低)的方法。


作为(~(-1)) === 0,因此:

1
!!(~(-1)) === Boolean(~(-1)) === Boolean(0) === false