JS奇淫技巧 骚操作

所谓的奇淫技巧,很奇异,很巧妙,很骚气的技巧。不知道各位有没有这种遭遇,看到某些人写的代码,简洁,奇异,又能正常运行不报错。其实只有对原理了解透彻才能写出来,看的人还一头雾水。
这里的奇淫技巧含义是骚操作

常见

!!

两次反转,会把一个类型转化为boolean类型,如 !!'this is true' ,等等。
自己也可以用,主要是很简洁,而且大部分人都懂。

if (A) {
    B()
}

// 简洁点一句代码搞定
!!A && B()

1en

比如

1e2 // 100
1e3 // 1000
1e5 // 100000

少见

>>> 无符号右移

来源于mittopen in new window,一个事件发布订阅开源模块,也是Vue3没了EventBus后推荐使用的第三方模块。看到这里第一眼觉得挺惊艳的。

首先解释下, >>> 是无符号右移。与 >> 的区别,在正数其实是一样的。

比如 5 >> 1 ,化为二进制就是 00000101 >> 1 , 结果二进制是 00000010 。同理 5 >>> 1 ,化为二进制就是 00000101 >>> 1 , 结果二进制还是 00000010 。因为无符号,所以左边是补0。

负数情况就略有不同了,我们知道计算机表达负数数值是取的补码。举个例子,我们用1和0表示 -7

  1. 第一位是符号位,正数是0,负数是1,所以得原码10000000 00000000 00000000 00000111
  2. 反码(符号位不变)得11111111 11111111 11111111 11111000
  3. 补码需要+1得11111111 11111111 11111111 11111001

所以 -7 在计算机里需要用 11111111 11111111 11111111 11111001 表示

  • 如果-7 >> 1,那么就是有符号右移,符号位不变,新补的位置取原符号位,就是1,得11111111 11111111 11111111 11111100。就是-4
  • 如果-7 >>> 1,那么就是无符号右移,先把符号位置为0,然后新补的位置取符号位,得01111111 11111111 11111111 11111100,可以用parseInt(01111111111111111111111111111100, 2) === -7 >>> 1验证

到这里都还正常,比较奇特的是 -1 的情况。

-1 的补码是 11111111 11111111 11111111 11111111 ,如果执行 -1 >> 0 ,那么符号位不变。
但是如果执行 -1 >>> 0 ,那么此时符号位就变了。 -1 >>> 0 ,会变为 01111111 11111111 11111111 11111111 ,就是4294967295。

这么无符号操作下来,原本的负数,变为了正整数。当在 Array.splice 这个方法使用的时候非常好,因为splice方法第一个参数start起始位置其实是接受负数的。

[1, 2, 3].splice(-1, 1) // [3],删除最后一个返回删除元素组成的新数组

[1, 2, 3].splice([1, 2, 3].indexOf(3), 1) // [3],删除最后一个返回删除元素组成的新数组
[1, 2, 3].splice([1, 2, 3].indexOf(8), 1) // [3],问题来了,这里没找到8这个数字,indexOf返回了-1,这个时候就把3删除了
[1, 2, 3].splice([1, 2, 3].indexOf(8) >>> 0, 1) // [],没找到8就不用删除了

以上实现了一个功能,数组如果能找到一个元素,就删除,否则不删除。例子的元素就是数字8,这就是mitt库的一个比较经典的用法

~

~ 表示NOT, 会反转所有位。

我们知道-1的补码是 11111111 11111111 11111111 11111111 ,那么 ~-1 就是0

这在if-else经常用到,如

if (~[1, 2, 3].indexOf(4)) { // 等价于 [1, 2, 3].indexOf(4) > -1
    console.log('数组没有4,这里不会执行到,never!!!')
} else {
    console.log('数组没有4,这里一直执行到')
}

双重~~

比较特殊的是0的情况,反转又反转。其实跟!!类似,负负得正,主要是负负得正的时候,会丢掉小数。

~0 //-1
~~0 //0

// 去除小数保留整数部分,原因是位运算操作要求是整数
~~0.1 // 0
~~1.23 // 1
~~-1.23 // -1

其实跟下面>>0<<0操作原理是一样的

1.2 >> 0 // 1
-1.2 << 0 // -1

%

如何判断一个数x是整数还是小数?比如1010.1,你可能会想说我看有没有小数点,这是形似而不是神似。其实数学含义可以判定,就是一个数 x%1为0则是整数,如果不为0就是小数

10 % 1 #0
10.0 % 1 #0
10.1 % 1 #0.09999999999999964
-10 % 1 #-0
-10.1 % 1 #-0.09999999999999964
0 % 1 #0
+0 % 1 #0
-0 % 1 #-0
0.00 % 1 # 0

所以判断一个数字是整数的话,可以用下面的判定。这里Number是为了过滤NaN等情况

Number(NaN) === NaN # false
function isInt(n){
    return Number(n) === n && n % 1 === 0;
}

function isFloat(n){
    return Number(n) === n && n % 1 !== 0;
}

所以判读一个数字为整数,则可被1整除。否则为浮点数

Last Updated:
<manfred>峯</hu>
欢迎关注微信公众号 【Big前端】无广告,无软文,就是这么傲娇。直推一线大厂高质量内容,不局限于前端·后台·运维相关,还包括房价🏠、信用卡💳等内容也可内推一线大厂腾讯阿里字节,对腾讯字节比较熟悉,简历可以发给我,我会给你介绍一线大厂的情况,让你更加了解一线大厂