JavaScript中的~运算符

最近看《JavaScript框架设计》这本书的2.4 EXT数组扩展这一节,intersect方法:对两个数组取交集。

js 复制代码
function intersect(target, array) {
    return target.filter(function(n) {
        return ~array.indexOf(n);
    });
}

第三行的~一时间没看懂,专程研究了一下。先使用一下上面的函数,如下:

js 复制代码
function intersect(target, array) {
    return target.filter(function(n) {
        return ~array.indexOf(n);
    });
}

let arr = [1, 2, 3];
let arr1 = [3, 6, 9];
console.log(intersect(arr, arr1)); // [3]

intersect第三行的~是按位非运算符。(其他位运算相关的文章 十进制的负数和十六进制间相互转换ECMAScript中的基本概念-位操作符JS中!!和~~的作用分别是什么,有什么区别?。)按位非运算符将操作数的位反转。如同其他位运算符一样,它将操作数转化为 32 位的有符号整型。比如数字5的按位非即是~5,这是怎么来的呢?~5是多少呢?看下面的演示。

js 复制代码
00000000000000000000000000000101     前面是数字5的32位二进制表示
11111111111111111111111111111010     对上面5的二进制表示按位取反,
                                     这里的值为-6,这是怎么来的呢?

ECMAScript中的基本概念-位操作符这里已经介绍过,负数同样以二进制码存储,但是使用二进制补码。计算一个数值的二进制补码步骤是这样的:

  • 先求这个负数的绝对值的二进制码
  • 在求以上二进制码的反码
  • 对以上得到的二进制反码加1

以-6为例,先把-6的绝对值,数字6用32位二进制表示,再对6的二进制按位取反,再对上一步的反码加1,如下:

js 复制代码
00000000000000000000000000000110     6的32位二进制表示
11111111111111111111111111111001     对6的二进制按位取反
11111111111111111111111111111010     对上一步的反码加1

可以看到这里的反码加1过后,同~5的二进制表示都是11111111111111111111111111111010 ,就可以得出~5 === -6。再拿一个负数-3的按位非~-3来推导一下。

js 复制代码
00000000000000000000000000000011     -3的绝对值3的二进制表示
11111111111111111111111111111100     对3的二进制按位取反
11111111111111111111111111111101     对上一步的反码加1,前面就是-3的二进制表示 
00000000000000000000000000000010     对上面的二进制表示按位取反,一眼就能看出是2

可以得出~-3 === 2,结合~5 === -6可以归纳出一个公式,对于数字n的按位非~n~n === -(n + 1),先把数字n1,再把以上的结果乘以-1,或~n === -n - 1,先把n乘以-1,再-1

最后回到上面的取交集函数intersect,遍历target中的项n, 如果array中也有这个遍历的子项n,那么array.indexOf(n)应该是大于等于零的,对于一个大于等于零的数取反~array.indexOf(n)的结果应该是小于零的,这种情况下为true,符合预期。如果array中没有这个遍历的子项n,那么array.indexOf(n)是等于-1的,对其取反~array.indexOf(n)~-10,这种情况下为false,也符合预期。到此取交集函数intersect分析完毕。

同时按位非运算符还有一个常用的场景就是对浮点数取整 ,另一篇文章JS中!!和~~的作用分别是什么,有什么区别? 中也有关于~~相关的介绍。

js 复制代码
~~3.1415926 // 3,~3.1415926结果为-4,~-4结果为3,就实现了取整

按位非~进行按位取反的过程中会将浮点数位去掉,只对前面32位整数进行处理,由于~的这个特性,小数点后面的部分是直接被去掉的,而不是进行Math.floor这样的四舍五入操作。

相关推荐
liangshanbo12151 小时前
写好 React useEffect 的终极指南
前端·javascript·react.js
_院长大人_4 小时前
el-table-column show-overflow-tooltip 只能显示纯文本,无法渲染 <p> 标签
前端·javascript·vue.js
SevgiliD4 小时前
el-table中控制单列内容多行超出省略及tooltip
javascript·vue.js·elementui
要加油哦~4 小时前
JS | 知识点总结 - 原型链
开发语言·javascript·原型模式
阿珊和她的猫5 小时前
深入理解与手写发布订阅模式
开发语言·前端·javascript·vue.js·ecmascript·状态模式
爱看书的小沐6 小时前
【小沐杂货铺】基于Three.js渲染三维风力发电机(WebGL、vue、react、WindTurbine)
javascript·vue.js·webgl·three.js·opengl·风力发电机·windturbine
qq_398586546 小时前
Threejs入门学习笔记
javascript·笔记·学习
浪裡遊7 小时前
Nivo图表库全面指南:配置与用法详解
前端·javascript·react.js·node.js·php
課代表7 小时前
JavaScript 二维数组的三种定义与初始化方法
javascript·初始化·二维数组·多维数组·动态数组·循环遍历·数组合并
鸡吃丸子8 小时前
Next.js 入门指南
开发语言·javascript·next.js