补码
在计算机系统中,数值用补码来表示。任何数值 n 的位反等于 -(n + 1):
1
|
~n === -(n + 1) |
可以得到:
1
2
3
4
5
6
7
8
|
~9 === -10 ~8 === -9 ~1 === -2 ~0 === -1 ~-1 === 0 ~-2 === 1 ~-9 === 8 ~-10 === 9 |
很明显,只有 ~-1 才等于 0. 对非 -1 值取反永远不为 0.
String#indexOf
String 的 indexOf 方法,找到时,返回自然数;没找到,则返回 -1. 常见代码:
1
2
3
|
if (str.indexOf('sub') !== -1) { // code } |
利用位反操作,可简化为:
1
2
3
|
if (~str.indexOf('sub')) { // code } |
更普适的规律是:
n !== -1
可简化为~n
n === -1
可简化为!~n
Array#indexOf
涉及状态判断时,很容易写出以下代码:
1
2
3
|
if (statusCode === 301 || statusCode === 302) { // code } |
利用 Array#indexOf, 上面的代码可简化成:
1
2
3
|
if ([301, 302].indexOf(statusCode) !== -1) { // code } |
用位反操作,可进一步简化:
1
2
3
|
if (~[301, 302].indexOf(statusCode)) { // code } |
类似的,可以:
1
2
3
|
if (~["loaded", "complete"].indexOf(readyState)) { // code } |
写在最后
一般来说,位反等简化方式有损可读性。可读性有两方面:
- 自己的代码给他人看。这时代码的通俗易懂很重要,尽量少用奇技淫巧。
- 自己看他人的代码。这时要让自己的知识面尽可能广,包括吃透各种奇技淫巧。
从学习的角度讲,吃透一些奇技淫巧,经常能深入到语言的部分底层细节,非常有益处。
还有一个不容忽视的现象:奇技淫巧有阶段性。好的技巧,在小圈子流行后,有可能会慢慢被大众接受,也就不再是奇技淫巧了,比如 (function(){ /* code */ })()
.
总之,技巧不怕多,权衡去用就好。