【本文会持续更新!】
1. 转换成数字
+
运算符
使用 +
运算符可以把其他类型转换成数字类型,但在使用时要注意表达式的结构,避免被解析成字符串连接符。
+'123'; // 123
+'123'+'456'; // "123456"
+'123'+(+'456'); // 579
~~
位运算符
按位非(~
)实质上是 对数字求负,然后减1。详细的处理过程请看 w3school: 位运算符。
~1; // -2
~-1; // 0
那么再次执行按位非即可取回原值:。
~~1; // 1
~~'1'; // 1
需要注意的是,~~
的方式只适合处理 32 位以下整数,若是浮点数会被取整。
~~1.2; // 1
~~-1.2; // -1
与 +
运算符相比,~~
运算符会把 undefined
或者不能转换成数字的值处理成 0
,在某些业务计算场景下这样的处理是有方便之处的。
+undefined; // NaN
+'abc'; // NaN
~~undefined; // 0
~~'abc'; // 0
实际上, +
运算符和 ~~
运算符都相当于使用 Number()
函数来处理,所以我们仍然需要关注一些特殊值的转换:
+'123', ~~'123'; // 123
+undefined, ~~undefined; // NaN
+null, ~~null; // 0
+true, ~~true; // 1
+false, ~~false; // 0
+[1], ~~[1]; // 1
当被转换值本身就是数字类型时,我们需要 小心被当成八进制数处理:
+010; // 8
+'010'; // '10'
2. 转换成字符串
+
运算符紧跟一个空字符串,就可以把其他类型转换成字符串类型。
1+''; // "1"
undefined+''; // "undefined"
null+''; // "null"
true+''; // "true"
[1,2]+''; // "1,2"
当被转换对象存在 toString()
的原型方法时,这种转换方式相当于调用了 toString()
函数:
new Date()+''; // "Thu May 16 2019 20:42:43 GMT+0800 (China Standard Time)"
new Date().toString(); // "Thu May 16 2019 20:42:43 GMT+0800 (China Standard Time)"
var o = {a: 1};
o+''; // "[object Object]"
o.toString(); // "[object Object]"
3. 转换成布尔值
由于逻辑非(!
)返回的一定是布尔值,所以通过双取反即可转换成布尔值。
!!0; // false
!!undefined; // false
!!'abc'; // true
!![] // true
!!{} // true
4. 短路求值
逻辑与(&&
)和逻辑或(||
)运算都是简便运算,即如果第一个运算数决定了结果,就不再计算第二个运算数,这就是短路求值。
利用短路求值可以大幅减少逻辑判断的代码量,但同时也会降低代码可读性。
var condition = true;
if (condition) {
console.log('It is true');
}
condition && console.log('It is true');
if (!condition) {
console.log('It is false');
}
condition || console.log('It is false');
逻辑与(&&
)表达式会返回第一个与 false
相等的值,而逻辑非(||
)表达式会返回第一个与 true
相等的值,都没有则返回最后一个运算数的值。
null && false; // null
1 && 2 && 3; // 3
1 || true; // 1
0 || false; // false
5. 浮点数取整
由于浮点数是不支持位运算的,所以在运算之前会把浮点数的小数部分去掉,也就相当于对浮点数进行了取整。
只需要满足位运算后不改变值的表达式,都可以视作快速取整的一种方式。
- 按位或
|
整数与 0
进行位或运算时,整数值不变,可用于浮点数取整。取整行为取决于浮点数是正数还是负数,正数时作向下取整,负数时作向上取整。
// 向下取整
Math.floor(12.3); // 12
12.3|0; // 12
// 向上取整
Math.ceil(-12.3); // -12
-12.3|0; // -12
需要注意位或运算取整和 Math.floor()
等取整函数在特殊值处理上的差异:
Math.floor(NaN); // NaN
NaN|0; // 0
Math.floor(Infinity); // Infinity
Infinity|0; // 0
-
~~
运算符
~~
运算符利用的就是两次位非运算(~
)后取回原值的特性,取整行为与位或运算一致。
~~12.3; // 12
~~-12.3; // -12
6. 奇偶判断
我们通常用取模运算符(%
)来判断奇偶性:
n % 2 === 1 ? 'n是奇数' : 'n是偶数';
当数字转成二进制表达时,判断奇偶性只需要看最后一位是 1
(奇数)还是 0
(偶数),所以我们可以通过与 1
进行按位与运算来判断奇偶性。
1 & 1; // 1
2 & 1; // 0
n & 1 ? 'n是奇数' : 'n是偶数';
7. 幂运算(ES7)
**
是 ES7 新增的幂运算符,详见 tc39提案。
Math.pow(2, 3); // 8
2**3; // 8
8. 整数交换
异或(^
)运算具有这样的性质:
- 满足交换律
- 满足结合律
- 自反性
所以通过三次异或运算可以完成两个整数值(A
、B
)的交换:
var a = 1;
var b = 2;
a = a ^ b; // 3
b = a ^ b; // 1
a = a ^ b; // 2
注意,异或运算不适合于浮点数及其他基本类型的变量交换。
除此之外,利用自反性异或运算还可以用于整数值的比较:运算结果为0则等值,非0则不等值。
1^1 = 0;
1^2 = 3;
9. void 0
很多 JS 框架、类库都会出现 void 0
这样的写法。void
运算符会对给定的表达式求值并返回 undefined
,所以
void 0 === undefined; // true
用 void 0
来替代 undefined
主要出于两点考虑:
- 节省代码的字节数;
-
undefined
可以被重写,而void
作为 JS 的关键字不能被重写;
ps:
undefined
在 ES5 中已经是全局对象的一个只读属性,但在局部作用域下依然能被局部变量覆盖。
undefined = 1;
console.log(undefined); // undefined
(function() {
var undefined = 1;
console.log(undefined); // 1
})();
网友评论