持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情
在一般开发中,位运算符用的比较少,自己对于这块的印象也基本上是停留在刚学习JavaScript的时候,现在对于这些运算符的记忆都有些模糊,有时候会搞混。
按位非(~)
它首先将操作数通过抽象操作ToInt32强制类型转换为 32 位数字,而ToInt32会先执行ToNumber强制类型转换,比如将“1234”转换为123,再执行ToInt32,超过32位的数字将会丢弃其最高有效位,然后将32位数字执行字位操作“非”(对每一个字位进行反转)。
const a = 5; // 00000000000000000000000000000101
const b = -3; // 11111111111111111111111111111101
实际上就是返回2的补码。
执行按位非运算的结果可以看成是-(x+1),比如~2的结果就是-(2+1)也就是-3,~-3的结果就是-(-3+1)也就是2。
开发中的用处
那么问题来了,要这个有什么用呢?平时开发也不需要这么算数呀。
实际上我们可以再想想什么时候~x的值会等于0,当x === -1的时候(事实上当x === 4294967295(2^32-1)的时候也等于0,32位二进制全是1,反转过来就是0,但是开发中基本不会碰到这个数字,这里只讨论-1的情况),为什么要这么想呢?
首先
0在JavaScript中是falsy(虚值),在条件语句和循环语句中会被转换为false。所以我们的按位非~可以用来进行一些条件判断。并且
-1是一个“哨位值”,哨位值是那些在各个类型中(这里是数字)被赋予了特殊含义的值。在C语言中我们用-1来代表函数执行失败,用大于等于0的值来代表函数执行成功。
JavaScript中有个常用的方法也遵循了这个惯例,没错就是indexOf(),这个方法当找到给定的子字符串或者数组元素的时候会返回对应的索引。它不仅能够找位置,实际上更多时候我们会用来找包含关系,然后做条件判断,比如:
const a = "JavaScript";
if (a.indexOf( "Sc" ) >= 0) { // true
}
if (a.indexOf( "Sc" ) != -1) { // true
}
if (a.indexOf( "sc" ) < 0) { // true
}
if (a.indexOf( "sc" ) == -1) { // true
}
>= 0和!= -1这样的写法不是很好,用-1作为失败时的返回值,这么做在代码中暴露了底层的实现细节,我们称之为“抽象渗漏”,这些细节应该被屏蔽掉。
到这里我们应该知道~在实际开发中能做些什么了,可以配合indexOf()将结果转换为真/假值。
const a = "JavaScript";
if (~a.indexOf( "Sc" )) { // true
}
if (!~a.indexOf( "Sc" )) { // false
}
if (~a.indexOf( "sc" )) { // false
}
if (!~a.indexOf( "sc" )) { // true
}
当indexOf()返回-1的时候,~将它转换为假值0,就可以通过条件语句进行判断。
由-(x+1)推断~-1的结果应该是-0,然而实际上结果是0,因为它是字位操作而非数学运算。
小白初来乍到,表述能力还有提升空间,欢迎大佬们指正,本文旨在熟悉和复习位运算符,大家也可以选用ES7的includes()实现相同需求,么么哒~