25

我正在阅读这篇博客文章,其中提到使用:

!!~ 

我不知道这是做什么的?起初我以为它会出错,但下面的代码确实运行了:

var _sessions = [
    "_SID_1",
    "_SID_2",
    "_SID_3",
    "_SID_4"
];

if(!!~_sessions.indexOf("_SID_5")) {
    console.log('found');
} else {
    console.log('!found');
}

输出:

node test.js 
!found
4

3 回答 3

28

~是按位非运算符。它反转其操作数的位。!是逻辑非运算符。按位非运算符将0在应用于 时返回-1,这是indexOf在数组中找不到值时返回的内容。由于0计算结果为false,双重否定它只会返回false(一个布尔值,而不是一个数字):

var index = _sessions.indexOf("_SID_5");
console.log(~index); // 0
console.log(!~index); // true
console.log(!!~index); //false

对于由 . 返回的任何其他可能值,按位非运算符将返回小于 0 的值indexOf。由于任何其他值都将评估为true,因此它只是一种检查元素是否存在于数组中的速记方法(有点......它们都是相同数量的字符!),而不是显式地与 进行比较-1

if (_sessions.indexOf("_SID_5") > -1) {
    // This would work the same way
}

更新

关于它的性能,它似乎(至少在 Chrome 中)比更常见的比较-1(它本身比与比较慢一点0)略慢。

这是一个测试用例,结果如下:

在此处输入图像描述

更新 2

实际上,您问题中的代码可以缩短,这可能是作者试图做的。您可以简单地删除!!,因为~将始终导致0或低于(并且0是唯一将评估为 的值false):

if (~_sessions.indexOf("_SID_5")) {
    // This works too
}

但是,在稍微不同的情况下,添加运算符可能是有意义的!。如果要将按位运算符的结果存储在变量中,它将是一个数值。通过应用逻辑非运算符,您可以获得一个布尔值(再次应用它可以确保您获得正确的布尔值)。-1如果由于某种原因您需要一个布尔值而不是数字值,那么它会更有意义(但您仍然可以使用or进行正常比较0):

var inArray = !!~_sessions.indexOf("_SID_5");
console.log(typeof inArray); // boolean
于 2012-11-28T11:13:13.547 回答
7

Donald Knuth:“[...] 过早优化是万恶之源”

为了可读性:请使用

.indexOf !== -1
于 2012-11-28T11:26:06.097 回答
5

这很好地解释了它:

Javascript 中的波浪号运算符

将两个 NOT 运算符混合在一起可以产生一些有趣的结果:

!~(-2) = 假

!~(-1) = 真

!~(0) = 假

!~(1) = 假

!~(2) = 假

所以这只是检查值是否等于 -1,如果没有找到匹配项,则 indexOf 返回 -1

于 2012-11-28T11:13:02.467 回答