如果您阅读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 |
我不明白这里的瓷砖的用途。有人能解释一下吗?或者给我指一个资源?
- 任何想写那样的代码的人都需要远离键盘。
- @柯克沃尔:为什么?~jQuery.inArray()实际上非常有用,甚至可能是搜索函数返回-1失败的一个非常好的原因(唯一的两个补码是错误的)。一旦你看到并理解了这个技巧,我觉得它比!= -1更可读。
- @阿玛丹——不,只是不。说真的,我不敢相信你是在为以东十一〔三〕辩护。
- @柯克沃尔:耸耸肩。事实上,我确实认为!!~是一种过度杀戮,因为JS处理好了真实/错误的值。但是作为对indexOf和inArray测试的!= -1的替代方法的一个简单的~,特别是在条件测试中,我绝对不会有问题。
- 问题是,它只是:一个"诡计"。在我看来,if (x != -1)和if (~x)的主要区别在于前者实际上表达了你的意图。后者表示您希望完全执行其他操作("请将我的64位数字转换为32位整数,并检查该整数的位非是否正确"),在这种情况下,您刚好可以得到所需的结果。
- @Kaneda:取决于你是否认为搜索函数返回的-1是一个巧合(这使得~成为一个丑陋的漏洞),还是作为一个设计决策(这使得~非常适合该特定的测试)。我不在乎x是-1——对我来说就像你的"请……"一样武断。我关心的是是否找到了一些东西;并且考虑到搜索函数有一个一致的API,返回-1表示"未找到",~是一种相当干净的测试方法。当你认识到$.indexOf(...) != -1是一个习语,而不是一个与-1相等的测试时,~是有意义的。
- 查看stackoverflow.com/questions/784929/…
- @20100-阅读问题…手术室已经把这个问题联系起来了,并说他已经读过了。
- 我的坏脾气。
- >= 0可能不够灵活,所以使用的!!~比较隐蔽。
- 普通人的方式对我来说更快。
- javascript Hipster…
- @从技术上讲,yoshi和EDOCX1的结果不同。foo != -1和!!~foo相当。
- @Minitech测试2应该是!==1,而不是>1
- @不,不应该。indexOf永远不会返回-2或更低。
- 如果你认为!!~比!= -1快:jsferf.com/faster-way-to-check-expr-not-equal-to-minus-one
- 可能重复了javascript中的~的含义
- @是的,但这套把戏解决了另一个"把戏"。inArrayUNF也不表示它打算做什么。~是使inArray"返回"布尔值的方法,它的名称意味着它在最少的击键次数下会返回。这是一种两种错误造成了一个正确的情况,尽管我同意这不是真正的理由。这家伙的isInArray是一个解决方案,因为inArray不能在不破坏现有代码的情况下进行更改。与伊纳瑞一起使用是有道理的,也许在一代人中这是个坏主意。
- 另请参见颚化符在表达式之前做什么?在javascript中,!!~是什么意思?
有时你会看到~在$.inArray前面应用,这是一个特殊的原因。
基本上,
是一个较短的方法
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
} |
它会按预期工作。
- 浏览器(现在是2014年)对此的支持程度如何?还是它一直都得到了完美的支持?
- 如果像这样的基本操作不完美,我会感到惊讶。
当expr为-1或true时,!!~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。
- 在一个稳定的库中,我看不到使用~foo.indexOf(bar)的问题,它不会显著地节省字符或性能,但它是一个相对常见的速记,与foo = foo || {}的方式相同。
- 这不是问题…至少在其他人被要求继续使用您的代码之前。
- @ZZZZBOV进一步阐述了萨尔曼的评论:总是把代码编写得好像维护代码的人是一个暴力的精神病患者,他知道你住在哪里。
- @Ahsteele,我很清楚这个规则,但是位运算符是我能想到的每种编程语言的一部分。我试着用一种对能读代码的人可读的方式编程。我不会因为别人不懂而停止使用语言的特性,否则我甚至无法使用!!。
- 严格来说,>= 0与!!~的行为不一样。!== -1更近了。
- 如果您从Access数据库中读取数据,会非常方便,因为false编码为-1和true0 IIRC。
- 很好的解释,我必须同意这个答案:如果你正在写你计划共享的代码,请不要这样做。你的同事/投稿人会感谢你的。
tilde操作符实际上根本不是jquery的一部分,它本身就是一个按位非操作符。
看到蒂尔德(~)的伟大神秘。
你在实验中得到了奇怪的数字,因为你正在对一个整数执行一个位逻辑运算(据我所知,它可能被存储为二的补码或类似的东西…)
二的补码解释了如何用二进制表示数字。我想我是对的。
- 第一个链接已断开
- 固定的!(把它改成另一个链接,奇怪的是,它是在我最初的答案之后写的…)
~foo.indexOf(bar)是表示foo.contains(bar)的常用缩写,因为contains函数不存在。
由于javascript的"错误"值概念,通常不需要强制转换为布尔值。在这种情况下,它用于强制函数的输出为true或false。
- 很好的解释,谢谢!
- +1这个答案解释了"为什么"比公认的答案更好。
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 |
- 这并不总是正确的,因为(例如)~2147483648 != -(2147483648 + 1)。
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; |
- 但是,还有3个字节要发送给客户机!编辑:(顺便说一句,开玩笑,发表了我的评论,意识到这并不明显(既悲伤又愚蠢)
- @韦斯利:是的,但它只需要发送给每个客户一次,假设客户机将缓存.js。尽管如此,他们可以使用>=0而不是!==-1,没有额外的字节来发送,而且比比特旋转版本更可读。
- 谁在跟踪谁?;)我认为编写可读代码比生成此类问题的加密预优化代码更好是理所当然的。稍后缩小,现在就可以编写可读的、可理解的代码。
- 我个人认为,> -1的可读性更高,但这可能是非常主观的。
~运算符是位非运算符。这意味着它需要一个二进制形式的数字,把所有的0变成1,把1变成0。
例如,二进制中的数字0是0000000,而-1是11111111。同样,1是二进制的00000001,而-2是11111110。
我的猜测是,它之所以存在,是因为它短了几个字符(图书馆的作者总是在追求)。它还使用在编译为本机代码时只需要几个机器周期的操作(而不是与数字进行比较)。
我同意另一个答案,即这是一个过度杀伤力,但可能在一个紧密的循环中是有意义的(尽管需要性能增益估计,否则可能是过早的优化)。
我假设,因为它是一个位操作,所以它是检查路径是否出现在modifiedpaths中的最快(计算成本较低)的方法。
作为(~(-1)) === 0,因此:
1
| !!(~(-1)) === Boolean(~(-1)) === Boolean(0) === false |
- 这也许是准确的,但对提问者来说这是一个有用的解释吗?一点也不。如果我一开始不明白,这样简明扼要的回答是没有帮助的。
- 我认为这个答案是有道理的。如果你有一个数学头脑,你可以清楚地看到在每个步骤中哪些部分在变化。这是这个问题的最佳答案吗?不,但它很有用,我想是的!+ 1