【JavaScript】位运算符 ~ 的作用详解
文章目录
JavaScript 作为一门动态语言,提供了多种运算符,其中 位运算符(Bitwise Operators) 是一组较少被使用但非常强大的运算符。本文将深入介绍
~(按位取反)运算符的作用、使用场景以及其在 JavaScript 开发中的实际应用。
一、~(按位取反)运算符简介
1. 什么是 ~ ?
~ 是 JavaScript 的 按位取反(Bitwise NOT) 运算符,它对数值的 每一位 进行翻转,即:
- 0 变成 1
- 1 变成 0
这个运算符的行为基于 32 位有符号整数 的二进制表示。它适用于 整数,但在 JavaScript 这种弱类型语言中,它也可以用于 隐式转换,甚至可以用于一些 特殊的技巧。
2. ~ 运算符的数学公式
在 JavaScript 中,~x 等价于:
~x = -(x + 1)
也就是说,~ 运算的结果是 负数,其值比原数字的相反数小 1。
示例:
console.log(~0); // -1
console.log(~1); // -2
console.log(~-1); // 0
console.log(~5); // -6
3. 为什么 ~x 等于 -(x + 1)?
让我们看一个 5 的二进制表示:
5 = 00000000 00000000 00000000 00000101 // 32 位二进制
~5 = 11111111 11111111 11111111 11111010 // 取反
在 JavaScript 的 二进制补码 规则下:
- 最高位
1表示负数 - 负数的二进制存储方式是 补码
取反后,11111111 11111111 11111111 11111010 在 补码表示 下的十进制数就是 -6,因此 ~5 = -6。
二、~ 运算符的应用场景
虽然 ~ 不是最常见的运算符,但它在某些场景中可以带来 简洁 和 高效 的代码。下面介绍几个常见的应用场景。
1. 快速判断值是否存在于数组
在 JavaScript 中,我们通常使用 indexOf 来检查某个值是否在数组中:
const arr = [1, 2, 3, 4, 5];
if (arr.indexOf(3) !== -1) {
console.log("3 存在于数组中");
}
但是可以使用 ~ 来简化:
if (~arr.indexOf(3)) {
console.log("3 存在于数组中");
}
为什么 ~indexOf(x) 可以判断值是否存在?
indexOf(x)返回-1时,表示找不到该元素~(-1) = 0,在if (~indexOf(x))语句中,0被视为false- 如果
indexOf(x)返回 非-1的索引,取反后仍然是一个 非零负数,在if判断中会被视为true
示例:
console.log(~[-1, 0, 1].indexOf(1)); // -2 (true)
console.log(~[-1, 0, 1].indexOf(-1)); // 0 (false)
console.log(~[-1, 0, 1].indexOf(0)); // -2 (true)
这种技巧在 ES6 引入 includes 之前非常流行,但现在 includes 更可读:
if (arr.includes(3)) {
console.log("3 存在于数组中");
}
2. 快速取反布尔值(仅适用于 0 和 -1)
由于 ~x = -(x + 1),它可以用于布尔值转换:
console.log(!!~1); // true
console.log(!!~0); // true
console.log(!!~-1); // false
console.log(!!~-100); // true
但 仅对 -1 有效,一般不建议这样使用,!! 更直观。
3. 用于二进制位操作
由于 ~ 直接作用于 二进制位,可以用于 掩码、反转标志位、快速计算补码 等操作:
const FLAGS = 0b10101010; // 170
const INVERTED_FLAGS = ~FLAGS;
console.log(INVERTED_FLAGS.toString(2)); // 11111111111111111111111101010101
示例: 如果 FLAGS 代表某些开关(如 10101010),那么 ~FLAGS 可以用来得到所有 相反的标志位(即 01010101)。
三、注意事项
1. 仅适用于 32 位整数
JavaScript 采用 IEEE 754 双精度浮点数 进行运算,但 位运算符会将操作数转换为 32 位有符号整数:
console.log(~5.5); // -6
console.log(~(5.9)); // -6
console.log(~(-5.9)); // 4
所以 ~ 不适用于浮点数运算,它会 强制转换为整数。
2. 慎用 ~indexOf() 技巧
虽然 ~indexOf(x) 很流行,但它的可读性不如 includes():
if (arr.includes(3)) { // 更直观
console.log("3 存在于数组中");
}
因此,在现代 JavaScript 代码中 推荐使用 includes()。
3. 负数取反变正数
由于 ~ 是对 补码 进行操作,所以对负数取反会 变成正数 -1:
console.log(~-1); // 0
console.log(~-2); // 1
console.log(~-3); // 2
可以利用这个特性进行某些 数学计算优化。
四、总结
JavaScript 的 ~(按位取反)运算符虽然 不常用,但它具有一些 独特的用途,特别是在:
- 判断
indexOf结果是否为-1 - 二进制掩码、标志位处理
- 特定布尔值转换
尽管它在 ES6 之后的应用场景减少,但在某些 低级优化 和 位运算 场景下依然有一定价值。
推荐:

更多推荐



所有评论(0)