数值的扩展
- Number.isFinite(), Number.isNaN()
- Number.parseInt(), Number.parseFloat()
- Number.isInteger()
- Math 对象的扩展
- 指数运算符
Number.isFinite()
定义和用法
isFinite() 函数用于检测指定参数是否为无穷大。
提示: 如果 number 是 NaN(非数字),或者是正、负无穷大的数,则返回 false。
Number.isFinite() 与全局的 isFinite() 函数不同,全局的 isFinite() 会先把检测值转换为 Number ,然后在检测。
Number.isFinite() 不会将检测值转换为 Number对象,如果检测值不是 Number 类型,则返回 false。
语法
Number.isFinite(value)
参数值
参数 | 描述 |
---|---|
value | 要检测的值。 |
返回值
类型 | 描述 |
---|---|
布尔型 | 如果是有限数字返回 true,否则返回 false。 |
栗子:检测参数是否为无穷大
<p id="demo"></p>
<p><strong>注意:</strong> IE 11 及更早 IE 版本不支持 Number.isFinite()函数。</p>
<script>
var res = "";
res +=Number.isFinite(123) + ": 123<br>";
res += Number.isFinite(-1.23) + ": -1.23<br>";
res += Number.isFinite(5-2) + ": 5-2<br>";
res += Number.isFinite(0) + ": 0<br>";
res += Number.isFinite('123') + ": '123'<br>";
res += Number.isFinite('Hello') + ": 'Hello'<br>";
res += Number.isFinite('2005/12/12') + ": '2005/12/12'<br>";
res += Number.isFinite(Infinity) + ": Infinity<br>";
res += Number.isFinite(-Infinity) + ": -Infinity<br>";
res += Number.isFinite(0 / 0) + ": 0 / 0<br>";
document.getElementById("demo").innerHTML = res;
</script>
結果為:
注意,如果参数类型不是数值,Number.isFinite
一律返回false
。
Number.isNaN()
定義:用来检查一个值是否为NaN
。
console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN('true'/0)); // true
// 在全局的 isNaN() 中,以下皆返回 true,因为在判断前会将非数值向数值转换
// 而 Number.isNaN() 不存在隐式的 Number() 类型转换,非 NaN 全部返回 false
Number.isNaN("NaN"); // false
Number.isNaN(undefined); // false
Number.isNaN({}); // false
Number.isNaN("true"); // false
如果参数类型不是NaN
,Number.isNaN
一律返回false
。
它们与传统的全局方法isFinite()
和isNaN()
的区别在于,传统方法先调用Number()
将非数值的值转为数值,再进行判断,而这两个新方法只对数值有效,Number.isFinite()
对于非数值一律返回false
, Number.isNaN()
只有对于NaN
才返回true
,非NaN
一律返回false
。
isFinite(25) // true
isFinite("25") // true
Number.isFinite(25) // true
Number.isFinite("25") // false
isNaN(NaN) // true
isNaN("NaN") // true
Number.isNaN(NaN) // true
Number.isNaN("NaN") // false
Number.isNaN(1) // false
Number.parseInt(), Number.parseFloat()
ES6 将全局方法parseInt()
和parseFloat()
,移植到Number
对象上面,行为完全保持不变。
// ES5的写法
parseInt('12.34') // 12
parseFloat('123.45#') // 123.45
// ES6的写法
Number.parseInt('12.34') // 12
Number.parseFloat('123.45#') // 123.45
这样做的目的,是逐步减少全局性方法,使得语言逐步模块化。
Number.parseInt === parseInt // true
Number.parseFloat === parseFloat // true
Number.isInteger()
定義:用于判断给定的参数是否为整数。
Number.isInteger(value)
Number.isInteger(0); // true
// JavaScript 内部,整数和浮点数采用的是同样的储存方法,因此 1 与 1.0 被视为相同的值
Number.isInteger(1); // true
Number.isInteger(1.0); // true
Number.isInteger(1.1); // false
Number.isInteger(Math.PI); // false
// NaN 和正负 Infinity 不是整数
Number.isInteger(NaN); // false
Number.isInteger(Infinity); // false
Number.isInteger(-Infinity); // false
Number.isInteger("10"); // false
Number.isInteger(true); // false
Number.isInteger(false); // false
Number.isInteger([1]); // false
// 数值的精度超过 53 个二进制位时,由于第 54 位及后面的位被丢弃,会产生误判
Number.isInteger(1.0000000000000001) // true
// 一个数值的绝对值小于 Number.MIN_VALUE(5E-324),即小于 JavaScript 能够分辨
// 的最小值,会被自动转为 0,也会产生误判
Number.isInteger(5E-324); // false
Number.isInteger(5E-325); // true
Math 对象的扩展
- Math.trunc()
Math.trunc
方法用于去除一个数的小数部分,返回整数部分。
Math.trunc(12.3); // 12
Math.trunc(12); // 12
// 整数部分为 0 时也会判断符号
Math.trunc(-0.5); // -0
Math.trunc(0.5); // 0
// Math.trunc 会将非数值转为数值再进行处理
Math.trunc("12.3"); // 12
// 空值或无法转化为数值时时返回 NaN
Math.trunc(); // NaN
Math.trunc(NaN); // NaN
Math.trunc("hhh"); // NaN
Math.trunc("123.2hhh"); // NaN
对于没有部署这个方法的环境,可以用下面的代码模拟。
Math.trunc = Math.trunc || function(x) {
return x < 0 ? Math.ceil(x) : Math.floor(x);
};
- Math.sign()
Math.sign
方法用来判断一个数到底是正数、负数、还是零。对于非数值,会先将其转换为数值。
它会返回五种值。
- 参数为正数,返回
+1
; - 参数为负数,返回
-1
; - 参数为 0,返回
0
; - 参数为-0,返回
-0
; - 其他值,返回
NaN
。
Math.sign(1); // 1
Math.sign(-1); // -1
// 参数为 0 时,不同符号的返回不同
Math.sign(0); // 0
Math.sign(-0); // -0
// 判断前会对非数值进行转换
Math.sign('1'); // 1
Math.sign('-1'); // -1
// 参数为非数值(无法转换为数值)时返回 NaN
Math.sign(NaN); // NaN
Math.sign('hhh'); // NaN
对于没有部署这个方法的环境,可以用下面的代码模拟。
Math.sign = Math.sign || function(x) {
x = +x; // convert to a number
if (x === 0 || isNaN(x)) {
return x;
}
return x > 0 ? 1 : -1;
};
- Math.cbrt()
Math.cbrt
方法用于计算一个数的立方根。
Math.cbrt(1); // 1
Math.cbrt(0); // 0
Math.cbrt(-1); // -1
// 会对非数值进行转换
Math.cbrt('1'); // 1
// 非数值且无法转换为数值时返回 NaN
Math.cbrt('hhh'); // NaN
对于没有部署这个方法的环境,可以用下面的代码模拟。
Math.cbrt = Math.cbrt || function(x) {
var y = Math.pow(Math.abs(x), 1/3);
return x < 0 ? -y : y;
};
- Math.imul()
Math.imul
方法返回两个数以 32 位带符号整数形式相乘的结果,返回的也是一个 32 位的带符号整数。
Math.imul(2, 4) // 8
Math.imul(-1, 8) // -8
Math.imul(-2, -2) // 4
如果只考虑最后 32 位,大多数情况下,Math.imul(a, b)
与a * b
的结果是相同的,即该方法等同于(a * b)|0
的效果(超过 32 位的部分溢出)。之所以需要部署这个方法,是因为 JavaScript 有精度限制,超过 2 的 53 次方的值无法精确表示。这就是说,对于那些很大的数的乘法,低位数值往往都是不精确的,Math.imul
方法可以返回正确的低位数值。
- Math.fround()
Math.fround
方法返回一个数的32位单精度浮点数形式。
对于32位单精度格式来说,数值精度是24个二进制位(1 位隐藏位与 23 位有效位),所以对于 -224 至 224 之间的整数(不含两个端点),返回结果与参数本身一致。
Math.fround(0) // 0
Math.fround(1) // 1
Math.fround(2 ** 24 - 1) // 16777215
如果参数的绝对值大于 224,返回的结果便开始丢失精度。
Math.fround(2 ** 24) // 16777216
Math.fround(2 ** 24 + 1) // 16777216
Math.fround
方法的主要作用,是将64位双精度浮点数转为32位单精度浮点数。如果小数的精度超过24个二进制位,返回值就会不同于原值,否则返回值不变(即与64位双精度值一致)。
// 未丢失有效精度
Math.fround(1.125) // 1.125
Math.fround(7.25) // 7.25
// 丢失精度
Math.fround(0.3) // 0.30000001192092896
Math.fround(0.7) // 0.699999988079071
Math.fround(1.0000000123) // 1
对于 NaN
和 Infinity
,此方法返回原值。对于其它类型的非数值,Math.fround
方法会先将其转为数值,再返回单精度浮点数。
Math.fround(NaN) // NaN
Math.fround(Infinity) // Infinity
Math.fround('5') // 5
Math.fround(true) // 1
Math.fround(null) // 0
Math.fround([]) // 0
Math.fround({}) // NaN
对于没有部署这个方法的环境,可以用下面的代码模拟。
Math.fround = Math.fround || function (x) {
return new Float32Array([x])[0];
};
- Math.hypot()
Math.hypot
方法返回所有参数的平方和的平方根。
Math.hypot(3, 4); // 5
Math.hypot(3, 4, 5); // 7.0710678118654755
Math.hypot(); // 0
Math.hypot(NaN); // NaN
Math.hypot(3, 4, 'foo'); // NaN
Math.hypot(3, 4, '5'); // 7.0710678118654755
Math.hypot(-3); // 3
上面代码中,3 的平方加上 4 的平方,等于 5 的平方。
如果参数不是数值,Math.hypot
方法会将其转为数值。只要有一个参数无法转为数值,就会返回 NaN。
指数运算符
ES2016 新增了一个指数运算符(**
)。
1 ** 2; // 1
// 右结合,从右至左计算
2 ** 2 ** 3; // 256
//多个指数运算符连用时,是从最右边开始计算的。
2 ** 3 ** 2
// 512
2 ** 2 // 4
2 ** 3 // 8
//指数运算符可以与等号结合,形成一个新的赋值运算符(**=)。
let exam = 2;
exam ** = 2; // 4
// 相当于 2 ** (3 ** 2)
let a = 1.5;
a **= 2;
// 等同于 a = a * a;
let b = 4;
b **= 3;
// 等同于 b = b * b * b;
注意,V8 引擎的指数运算符与Math.pow
的实现不相同,对于特别大的运算结果,两者会有细微的差异。
Math.pow(99, 99)
// 3.697296376497263e+197
99 ** 99
// 3.697296376497268e+197
上面代码中,两个运算结果的最后一位有效数字是有差异的。