JS中的数值运算

虽然有不少坑但是比较可靠的parseInt

Number.parseInt(string,radix) 默认接收两个参数

  第一个参数是默认是 string 类型值,如果不是,会通过抽象的 ToString 强制转化成 string 类型的值。这其中就会有强制类型转换过程中的各种坑

  第二个参数是 number 类型的进制,如果不是,会通过抽象的 ToNumber 强制转化成 number 类型的值,范围是 2-36,通过强制类型转换后如果是其他值会返回 NaN。在 ES5 之前如果没有传入这个参数,会根据第一个参数的开头来判断进制,0 开头的字符串会判断成八进制,也就是很多人提到的老黄历坑。ES5 之后已经解决,不传这个参数默认十进制。但是这个参数容易被忽略,尤其是在和 map 之类的也容易忽略后续可选参数的函数搭配使用的时候,比如

1
2
["1", "2", "3"].map(parseInt) // 结果是 [1, NaN, NaN]
["1", "2", "3"].map(x=>parseInt(x,10)) //正确的做法

这里第一个结果是[1, NaN, NaN]的原因为:

  map方法在调用callback函数时,会给它传递三个参数:当前正在遍历的元素, 元素索引, 原数组本身.

  第三个参数parseInt会忽视, 但第二个参数不会,也就是说,parseInt把传过来的索引值当成进制数来使用.从而返回了NaN。

  即实际是下面这样:

1
2
3
parseInt("1", 0); // 这是特例, 按照 0 进制转成数, 直接得本身
parseInt("2", 1); // 直接NaN, 因为计数的进制至少也是 2 进制
parseInt("3", 2); // 也是NaN, 因为二进制只有0,1

  所以如果只是用 parseInt 来 “取整”,一个良好的习惯是永远记得设置第二个参数为 10

  最后提一点,在ES6中将全局对象的parseInt()和parseFloat()移植到了Number对象上面,行为完全不变。但Number.isFinite()和Number.isNaN()则是在内层借用了全局的相应方法,所以只能说ES6在Number对象上提供了isFinite()和isNaN()方法。

1
2
3
alert(isFinite===Number.isFinite);  //false
alert(isNaN===Number.isNaN); //false
alert(parseInt===Number.parseInt); //true

巧妙使用位操作符

  JavaScript 中的 number 类型的值都是使用 IEEE 754 标准的 64 位双精度浮点型存储,即 1 位符号位 + 11 位指数部分 + 52 位尾数部分 。用来表示整数时,安全的范围是 53 位,超出这个返回可能会造成精度丢失

  1. 按位或| 向下取整(数值不够大才能用)
1
2
3
4
5
6
7
var num=-9999999.1234;
var int=num|0;
console.log(int); //-9999999

var num=-9999999999.1234;
var int=num|0;
console.log(int); //-1410065407

关于其它的取整方法可以见博客中:“JS中的取整”

  1. 按位非~(按位取反)任意数值x相当于-(x+1)
1
2
3
4
5
6
console.log(~1);    //-2
console.log(~0); //-1
console.log(~-1); //0

console.log(~NaN); //-1
console.log(~[]); //-1

  我们可以发现:-1 是唯一一个经过 ~ 运算返回假值0的值(包括其他那些特殊的值比如 NaN、{}、[] 等都不会返回假值)

  所以字符串和数组的 indexOf 函数查找失败会返回 -1,这时候就可以用:

1
if(~str.indexOf('str')) // 来表示查找失败

比判断 >= 0 或者 != -1 更优雅,跟用 !! 来判断非假值有异曲同工之妙

  1. 按位与&取最后一位数字

  eg:取任意数字的任意二进制位上的值(不是1就是0)
eg:128的第一到第7位是0,第八位是1(128=10000000)

1
2
3
4
5
6
7
8
9
10
/*
主要方法是和1按位与,
如10000
&
00001,这样就能取到10000的最后一位数字
*/
function valueAtBit(num,bit){
return (num>>(bit-1)) & 1;
}
console.log(valueAtBit(128,8)); //1

其它的骚操作

  JS取0~9的一个随机数可以用:

1
(Math.random()+"").slice(-1);   //eg从0.984652315464中复制最后一个数字4