ccforward / cc

Code & Blog
1.59k stars 193 forks source link

14.使用 ~ 和 indexOf 来判断一个元素是否在数组中 #15

Open ccforward opened 9 years ago

ccforward commented 9 years ago

引子

判断一个元素是否在数组中,代码很简单,也就一个 if 判断了事

var t = {val:2};
if([1,2,3,4,5].indexOf(t.val) >= 0){
    alert('Yes');
}

PS:indexOf 来自 ES5 ,IE9一下不支持

使用 ~ 符号却能简化判断语句,如下:

if( ~[1,2,3,4,5].indexOf(t.val) ){
    // other things
}

Why

如果一个元素存在于数组中,indexOf() 则返回它的索引;不存在,返回 -1。 细节怎么的不重要,因为 ~ 就是个位操作符(按位非),反转操作数的比特位,只有-1才会返回0。

按位操作符

More

整数在 js 中是被符号化的,意味着最左侧的一个bit用来表示符号位;也就是一个表示帧数负数的标记,1开始表示为负数,32位表示如下

1 :    00000000000000000000000000000001
2 :    00000000000000000000000000000010
3 :    00000000000000000000000000000011
15:    00000000000000000000000000001111

对应的负数:

-1 :   11111111111111111111111111111111
-2 :   11111111111111111111111111111110
-3 :   11111111111111111111111111111101
-15:   11111111111111111111111111110001

二进制中正负数原码 反码不必多说。

下面简单的二进制计算 来展示 -1 + +1 是如何运算的

   00000000000000000000000000000001      +1
+  11111111111111111111111111111111      -1
-------------------------------------------
=  00000000000000000000000000000000       0

以及 -15 + +15

   00000000000000000000000000001111      +15
+  11111111111111111111111111110001      -15
--------------------------------------------
=  00000000000000000000000000000000        0

从最右侧开始相加,1+1=2 也就是 10 把1向前借位,然后一直循环到最左侧,直到最后一个借位的 1 无处可去,于是就 溢出 overflow 了,然后就丢失了,我们只剩下一堆的 0 ,结果于是就是 0

总之

-1 这个数是为一个其二进制码全是 1 的数字,因此使用 ~ 这个按位取反符号后,它的所有二进制数位全部反转。

所以这大段的文其实就只是解释了 按位取反后只有-1才会返回0。

HualiangLI commented 6 years ago

这个涉及到代码的可读性,不太建议用 ~,毕竟不常用,其他人读到这行代码可能会被卡住

miaoyuxinbaby commented 6 years ago

我也用过~一段时间,后来就不用了