本文已参与掘金创作者训练营第三期「话题写作」赛道,详情查看:掘力计划|创作者训练营第三期正在进行,「写」出个人影响力。
相信很多小伙伴第一次看到 Javascript 这些运算符号时,一脸懵逼。我不一样,初看懵逼我闪了,所以看到这些运算符,两脸懵逼。为了避免看不懂同事写的牛逼代码,整理此文。
位运算符
|
&
~
~~
^
>>
<<
这些都是二进制操作符,直接在数值的二进制形式上进行操作。
按位或 |
直接对数字的二进制形式进行运算,每位有一个为1则是1。
var i = 8 | 1
console.log(i); // 9
复制代码
8 = 0000 0000 0000 0000 0000 0000 0000 1000
1 = 0000 0000 0000 0000 0000 0000 0000 0001
--------------------------------------------
OR = 0000 0000 0000 0000 0000 0000 0000 1001
复制代码
二进制 1001
转为10进制为9。
按位与 &
直接对数字的二进制形式进行运算,每位都为1才是1,否则为0。
var i = 10 & 3
console.log(i); // 2
复制代码
10 = 0000 0000 0000 0000 0000 0000 0000 1010
3 = 0000 0000 0000 0000 0000 0000 0000 0011
--------------------------------------------
AND = 0000 0000 0000 0000 0000 0000 0000 0010
复制代码
二进制 0010
转为10进制为2。
按位异或 ^
直接对数字的二进制形式进行运算,每位相等则为0,不相等为1。
var i = 10 ^ 3
console.log(i); // 9
复制代码
10 = 0000 0000 0000 0000 0000 0000 0000 1010
3 = 0000 0000 0000 0000 0000 0000 0000 0011
--------------------------------------------
XOR = 0000 0000 0000 0000 0000 0000 0000 1001
复制代码
二进制 1001
转为10进制为9。
按位非 ~
直接对数字的二进制形式进行运算,对任一数值 x 进行按位取反操作。
var i = ~5
console.log(i); // -6
复制代码
其结果为 -(x + 1),计算原理如下:
5 = 0000 0000 0000 0000 0000 0000 0000 0101
~ = 1111 1111 1111 1111 1111 1111 1111 1010
--------------------------------------------
32位开头第一个是1,所以这是一个负数。
将二进制转换成负数,需要先反码之后,再+1,转为10进制之后,加上负数。
反码 = 0000 0000 0000 0000 0000 0000 0000 0101
反码+1 = 0000 0000 0000 0000 0000 0000 0000 0110 (转换成十进制为6)
转换成十进制为6,加上符号变成负数 -6
复制代码
对 ~x
再次取反就是 ~~x
, 就为 -(-(x+1) + 1)。
对于浮点数,~~value
可以代替 parseInt(value)
。
console.log(~~10.5) // 10
console.log(~~-10.5) // -10
复制代码
而且前者效率更高些。虽然 ~~
他的缺点是难懂,但优点是可以用来装*哇。
var count = 5000000;
var h = 2.101;
console.time('parseInt');
for (var i = count; i > 0; i--) {
parseInt(h);
}
console.timeEnd('parseInt'); // 55.91796875 ms
console.time('~~');
for (var i = count; i>0; i--) {
~~h;
}
console.timeEnd('~~'); // 21.987060546875 ms
复制代码
右移 >>
右移操作符将第一个操作数向右移动指定位数,右边超出的位数将会被清除,左边将会补零。
var i = 10 >> 3
console.log(i); // 1
var j = 4 >> 3
console.log(j); // 0
复制代码
10 = 0000 0000 0000 0000 0000 0000 0000 1010
--------------------------------------------
>>3 = 0000 0000 0000 0000 0000 0000 0000 0001
4 = 0000 0000 0000 0000 0000 0000 0000 0100
--------------------------------------------
>>2 = 0000 0000 0000 0000 0000 0000 0000 0000
复制代码
二进制 0001
转为10进制为1,0000
为0。
左移 <<
左移操作符将第一个操作数向左移动指定位数,左边超出的位数将会被清除,右边将会补零。
var i = 1 << 3
console.log(i); // 8
复制代码
1 = 0000 0000 0000 0000 0000 0000 0000 0001
--------------------------------------------
<< 3 = 0000 0000 0000 0000 0000 0000 0000 1000
复制代码
二进制 1000
转为10进制为8。
其他非二进制运算符
幂运算符 **
幂运算符 (**) 返回将第一个操作数和第二个操作数求幂的结果。它等同于 Math.pow,但它也接受 BigInts 作为操作数。
console.log(3 ** 4);
console.log(Math.pow(3, 4));
// expected output: 81
console.log(10 ** -2);
console.log(Math.pow(10, -2));
// expected output: 0.01
复制代码
求幂运算符是右结合的:a ** b ** c 等于 a ** (b ** c)。
console.log(3 ** 2 ** 2);
console.log(3 ** (2 ** 2));
// expected output: 81
复制代码
但注意哦,如果底数为负数的话,请用以下语法。
(-4) ** 2
// expected output: 16
复制代码
或者如果你期待对求幂之后的数取反,应该如下:
- (4 ** 2)
// expected output: -16
复制代码
使用模棱两可的语法,会报错。
- 4 ** 2
// Uncaught SyntaxError: Unary operator used immediately before exponentiation expression. Parenthesis must be used to disambiguate operator precedence
复制代码
幂赋值运算符 **=
幂赋值运算符 (**=) 将变量赋值为其初识值和等号右边的值求幂后的值。
let a = 3;
console.log(a **= 2);
// expected output: 9
console.log(a **= 0);
// expected output: 1
console.log(a **= 'hello');
// expected output: NaN
复制代码
空值合并操作符 ??
空值合并操作符( ??
)是一个逻辑操作符,当左侧的操作数为 null
或者 undefined
时,返回其右侧操作数,否则返回左侧操作数。
var a = null;
var b = undefined;
var aa = a ?? 'xxx'
console.log(aa) // 'xxx'
var bb = b ?? 'yyy'
console.log(bb) // 'yyy'
复制代码
初看和 ||
很相像,请看当左值为 0 或 '' 时的区别
var a = 0;
var b = '';
console.log(a ?? 'xxx') // 0
console.log(a || 'xxx') // xxx
console.log(b ?? 'yyy') // ''
console.log(b || 'yyy') // yyy
复制代码
??
只在左侧的操作数为 null
或者 undefined
时,返回右值,谨记。
数字分隔符 _
碰到一个长数字数不过来,不知道它有几位?es 新标准 数字分隔符 _
就是用来解决这个问题的。
准确来说,它并不是运算符。为了凑数,而放进来的。它的提议见 github.com/tc39/propos… 。
let budget = 1_000_000_000_000;
// 它是一个数字,不信可以确认
console.log(budget === 10 ** 12); // true
let budget2 = 1_000
console.log(budget2 === 10 ** 3); // true
复制代码
有没有觉得很清爽。
参考致谢
感谢阅读,写得头发都秃了,你懂的。