[本文会持续更新!]
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
- })();
来源: http://www.jianshu.com/p/0be59b8f7a83