本文为电子书《ECMAScript 6 入门》:ES6入门教程学习笔记
数值的扩展
1. 二进制和八进制表示
引入了前缀0b和0o
0b111110111 === 503 //true
0o767 === 503 //true
二进制和八进制转为十进制要使用Number()方法。
2. 数值分隔符
ES2021允许使用下划线_作为分隔符,注意点如下
不能放在数值的最前面(leading)或最后面(trailing)。
不能两个或两个以上的分隔符连在一起。
小数点的前后不能有分隔符。
科学计数法里面,表示指数的e或E前后不能有分隔符。
3. Number的新方法
3.1 Number.isFinite()
用来判断数字是否有限,同时如果参数不是数值类型则返回false,而全局方法isFinite()会先将非数值的值转化为数值再进行判断。
Number.isFinite(15); // true
Number.isFinite(0.8); // true
Number.isFinite(NaN); // false
Number.isFinite(Infinity); // false
Number.isFinite(-Infinity); // false
Number.isFinite('foo'); // false
Number.isFinite('15'); // false
Number.isFinite(true); // false
isFinite(25) // true
isFinite("25") // true
3.2 Number.isNaN()
用来检测数字是否为NaN,同上,如果参数类型不是数值返回false,全局方法isNaN会进行转化。
Number.isNaN(NaN) // true
Number.isNaN(15) // false
Number.isNaN('15') // false
Number.isNaN(true) // false
Number.isNaN(9/NaN) // true
Number.isNaN('true' / 0) // true
Number.isNaN('true' / 'true') // true
isNaN(NaN) // true
isNaN("NaN") // true
3.3 Number.parseInt()
全局方法parseInt()移植而来,行为不变。
3.4 Number.parseFloat()
全局方法parseFloat()移植而来,行为不变。
3.5 Number.isInteger()
具体规则见代码
Number.isInteger(25) // true
Number.isInteger(25.1) // false
Number.isInteger(25.0) // true
Number.isInteger() // false
Number.isInteger(null) // false
Number.isInteger('25') // false
Number.isInteger(true) // false
JS中数值存储为64位双精度格式,数值精度最多可以达到53个二进制位,第54位及以后的位会被丢弃,导致误判:
Number.isInteger(3.0000000000000002) // true
3.6 Number.EPSILON
表示JS的最小精度,相当于2的-52次方,主要是为了给浮点数计算设置一个误差范围,比如,误差范围设为 2 的-50 次方(即Number.EPSILON * Math.pow(2, 2)),即如果两个浮点数的差小于这个值,我们就认为这两个浮点数相等
function withinErrorMargin (left, right) {
return Math.abs(left - right) < Number.EPSILON * Math.pow(2, 2);
}
0.1 + 0.2 === 0.3 // false
withinErrorMargin(0.1 + 0.2, 0.3) // true
1.1 + 1.3 === 2.4 // false
withinErrorMargin(1.1 + 1.3, 2.4) // true
3.7Number.isSafeInteger()
JavaScript 能够准确表示的整数范围在-253到253之间(不含两个端点),超过这个范围,无法精确表示这个值。ES6 引入了Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER这两个常量,用来表示这个范围的上下限。Number.isSafeInteger()则是用来判断一个整数是否落在这个范围之内。
4. Math的新方法
4.1 Math.trunc()
用于去除一个数的小数部分,返回整数部分,并将非数值转化为数值,其余不符合条件的返回NaN。
Math.trunc(4.1) // 4
Math.trunc(4.9) // 4
Math.trunc(-4.1) // -4
Math.trunc(-4.9) // -4
Math.trunc(-0.1234) // -0
Math.trunc('123.456') // 123
Math.trunc(true) //1
Math.trunc(false) // 0
Math.trunc(null) // 0
Math.trunc(NaN); // NaN
Math.trunc('foo'); // NaN
Math.trunc(); // NaN
Math.trunc(undefined) // NaN
null转化成数值类型竟然是0。
4.2 Math.sign()
用来判断一个数是整数负数或0
Math.sign(-5) // -1
Math.sign(5) // +1
Math.sign(0) // +0
Math.sign(-0) // -0
Math.sign(NaN) // NaN
Math.sign('') // 0
Math.sign(true) // +1
Math.sign(false) // 0
Math.sign(null) // 0
Math.sign('9') // +1
Math.sign('foo') // NaN
Math.sign() // NaN
Math.sign(undefined) // NaN
4.3 Math.cbrt()
用来计算一个数的立方根
4.4 Math.imul()
返回两个数以32位带符号整数相乘的结果,比*运算符的精度更高
4.5 Math.fround()
返回一个数的单精度浮点数形式,主要用于将64位双精度浮点数转化为32位单精度浮点数,如果小数的精度超过24个二进制位,返回值就会不同于原值,否则返回值不变
4.6 Math.hypot()
返回所有参数的平方和的平方根。
4.7 对数
Math.expm1(x)返回 ex - 1,即Math.exp(x) - 1。
Math.log1p(x)方法返回1 + x的自然对数,即Math.log(1 + x)。如果x小于-1,返回NaN。
Math.log10(x)返回以 10 为底的x的对数。如果x小于 0,则返回 NaN。
Math.log2(x)返回以 2 为底的x的对数。如果x小于 0,则返回 NaN。
5. BigInt
JS中所有数字都是64位双精度浮点数,进而导致数值的精度只能精确到53个二进制位,及16个十进制位,大于这个范围的整数无法精确表示,大于或等于2的1024次方的数也会无法表示,返回Infinity。BigInt就是用来解决这个问题的,为了与Number区分,数字后加n。并原生提供BigInt函数。
运算符的扩展
1. 指数运算符
这个运算符的一个特点是右结合,而不是常见的左结合。多个指数运算符连用时,是从最右边开始计算的。指数运算符可以与等号结合,形成一个新的赋值运算符(**=)。
// 相当于 2 ** (3 ** 2)
2 ** 3 ** 2
// 512
let a = 1.5;
a **= 2;
// 等同于 a = a * a;
let b = 4;
b **= 3;
// 等同于 b = b * b * b;
2. 链判断运算符
在对对象进行多层的属性获取时,其实正确的写法是对每一层都进行一次空判:
// 错误的写法
const firstName = message.body.user.firstName || 'default';
// 正确的写法
const firstName = (message
&& message.body
&& message.body.user
&& message.body.user.firstName) || 'default';
为了避免这种复杂的写法,ES2020引入了链判断运算符?.:
const firstName = message?.body?.user?.firstName || 'default';
const fooValue = myForm.querySelector('input[name=foo]')?.value
有三种写法。
obj?.prop // 对象属性是否存在
obj?.[expr] // 同上
func?.(…args) // 函数或对象方法是否存在
3. Null判断运算符
Null判断运算符类似||,但是||会将null和undefined与空字符串/false/0混淆,因此推出??运算符,主要使用场景是给空值设置默认值
4. 逻辑赋值运算符
// 或赋值运算符
x ||= y
// 等同于
x || (x = y)
// 与赋值运算符
x &&= y
// 等同于
x && (x = y)
// Null 赋值运算符
x ??= y
// 等同于
x ?? (x = y)
5. #!命令
ES2023 为 JavaScript 脚本引入了#!命令,写在脚本文件或者模块文件的第一行。
// 写在脚本文件第一行
#!/usr/bin/env node
'use strict';
console.log(1);
// 写在模块文件第一行
#!/usr/bin/env node
export {};
console.log(1);
有了这一行以后,Unix 命令行就可以直接执行脚本。
# 以前执行脚本的方式
$ node hello.js
# hashbang 的方式
$ ./hello.js