ES6 对数值类型做了多项增强,包括新的字面量语法、Number 对象新方法、Math 对象扩展等。
数值字面量#
二进制和八进制#
ES6 新增了二进制(0b)和八进制(0o)字面量前缀:
// 二进制(Binary)const bin = 0b1010console.log(bin) // 10
// 八进制(Octal)const oct = 0o17console.log(oct) // 15
// 十六进制(已有)const hex = 0xffconsole.log(hex) // 255
// 转换为二进制/八进制字符串;(10).toString(2) // '1010';(15).toString(8) // '17';(255).toString(16) // 'ff'实际应用:
// 位掩码更直观const READ = 0b0001 // 1const WRITE = 0b0010 // 2const EXECUTE = 0b0100 // 4
const permission = READ | WRITE // 0b0011 = 3
// 检查权限const hasRead = (permission & READ) !== 0 // trueconst hasExecute = (permission & EXECUTE) !== 0 // false
// 文件权限(类似 Linux)const FILE_PERMISSION = 0o755 // rwxr-xr-x数值分隔符#
ES2021 允许用下划线 _ 分隔数字,提高可读性:
const billion = 1_000_000_000const bytes = 0xff_ff_ff_ffconst bits = 0b1010_0001_1000_0101
// 小数也可以const pi = 3.141_592_653
// 科学计数法const avogadro = 6.022_140_76e23
// 不能放在特殊位置// const bad = _1000; // 错误// const bad = 1000_; // 错误// const bad = 1__000; // 错误// const bad = 1._5; // 错误Number 新属性#
Number.EPSILON#
表示 1 与大于 1 的最小浮点数之差:
Number.EPSILON // 2.220446049250313e-16
// 用于浮点数比较function equal(a, b) { return Math.abs(a - b) < Number.EPSILON}
0.1 + 0.2 === 0.3 // falseequal(0.1 + 0.2, 0.3) // trueNumber.MAX_SAFE_INTEGER / MIN_SAFE_INTEGER#
安全整数范围:
Number.MAX_SAFE_INTEGER // 9007199254740991 (2^53 - 1)Number.MIN_SAFE_INTEGER // -9007199254740991
// 超出范围会丢失精度9007199254740992 === 9007199254740993 // true(危险!)Number.isFinite()#
判断是否为有限数(不会进行类型转换):
// 全局 isFinite 会转换类型isFinite('25') // trueisFinite(null) // true
// Number.isFinite 不转换Number.isFinite('25') // falseNumber.isFinite(null) // falseNumber.isFinite(25) // trueNumber.isFinite(Infinity) // falseNumber.isFinite(NaN) // falseNumber.isNaN()#
判断是否为 NaN(不会进行类型转换):
// 全局 isNaN 会转换类型isNaN('NaN') // true(字符串转换后是NaN)isNaN(undefined) // true
// Number.isNaN 不转换Number.isNaN('NaN') // falseNumber.isNaN(undefined) // falseNumber.isNaN(NaN) // trueNumber.isInteger()#
判断是否为整数:
Number.isInteger(25) // trueNumber.isInteger(25.0) // trueNumber.isInteger(25.1) // falseNumber.isInteger('25') // falseNumber.isInteger(null) // false🔶 注意精度问题:
Number.isInteger(3.0000000000000002) // true(精度丢失)Number.isSafeInteger()#
判断是否在安全整数范围内:
Number.isSafeInteger(3) // trueNumber.isSafeInteger(9007199254740991) // trueNumber.isSafeInteger(9007199254740992) // false
// 实际应用:验证计算结果function safeAdd(a, b) { if (!Number.isSafeInteger(a) || !Number.isSafeInteger(b)) { throw new Error('数值超出安全范围') } const result = a + b if (!Number.isSafeInteger(result)) { throw new Error('计算结果超出安全范围') } return result}Number.parseInt() / parseFloat()#
从全局移植到 Number 对象,行为完全一致:
Number.parseInt('12.34') // 12Number.parseFloat('12.34') // 12.34
// 与全局方法相同Number.parseInt === parseInt // trueNumber.parseFloat === parseFloat // trueMath 扩展#
Math.trunc()#
去除小数部分,只保留整数:
Math.trunc(4.9) // 4Math.trunc(-4.9) // -4Math.trunc(0.123) // 0
// 与其他取整方法对比const n = -4.7Math.trunc(n) // -4(直接截断)Math.floor(n) // -5(向下取整)Math.ceil(n) // -4(向上取整)Math.round(n) // -5(四舍五入)Math.sign()#
判断数值的符号:
Math.sign(5) // 1Math.sign(-5) // -1Math.sign(0) // 0Math.sign(-0) // -0Math.sign(NaN) // NaN实际应用:
function compareNumbers(a, b) { const sign = Math.sign(a - b) if (sign === 1) return 'a > b' if (sign === -1) return 'a < b' return 'a = b'}Math.cbrt()#
计算立方根:
Math.cbrt(8) // 2Math.cbrt(-8) // -2Math.cbrt(27) // 3Math.clz32()#
返回 32 位整数前导零的个数:
Math.clz32(1) // 31(0b00000000000000000000000000000001)Math.clz32(2) // 30(0b00000000000000000000000000000010)Math.clz32(0) // 32
// 计算最高位function highestBit(n) { return 31 - Math.clz32(n)}highestBit(8) // 3(2^3 = 8)Math.imul()#
32 位整数乘法:
// 普通乘法可能溢出0x7fffffff * 0x7fffffff // 4611686014132420600(不精确)
// imul 返回正确的 32 位结果Math.imul(0x7fffffff, 0x7fffffff) // 1Math.fround()#
返回最接近的 32 位单精度浮点数:
Math.fround(1.337) // 1.3370000123977661Math.fround(1.5) // 1.5(正好可以表示)
// 用于模拟 32 位浮点运算Math.hypot()#
计算所有参数的平方和的平方根:
// 勾股定理Math.hypot(3, 4) // 5
// 三维距离Math.hypot(3, 4, 5) // 7.0710678118654755
// 实际应用:计算两点距离function distance(p1, p2) { return Math.hypot(p2.x - p1.x, p2.y - p1.y)}distance({ x: 0, y: 0 }, { x: 3, y: 4 }) // 5对数方法#
// 以 e 为底Math.expm1(1) // e^1 - 1 = 1.718...Math.log1p(Math.E - 1) // ln(e) = 1
// 以 10 为底Math.log10(100) // 2
// 以 2 为底Math.log2(8) // 3
// 实际应用:计算数字位数function digitCount(n) { return Math.floor(Math.log10(Math.abs(n))) + 1}digitCount(12345) // 5双曲函数#
Math.sinh(x) // 双曲正弦Math.cosh(x) // 双曲余弦Math.tanh(x) // 双曲正切Math.asinh(x) // 反双曲正弦Math.acosh(x) // 反双曲余弦Math.atanh(x) // 反双曲正切实战应用#
金额计算#
// 避免浮点数精度问题,转为整数计算function add(a, b) { const factor = 100 return (Math.round(a * factor) + Math.round(b * factor)) / factor}
add(0.1, 0.2) // 0.3
// 更通用的方案function safeCalculate(a, b, operation) { const aStr = String(a) const bStr = String(b) const aDecimals = (aStr.split('.')[1] || '').length const bDecimals = (bStr.split('.')[1] || '').length const factor = Math.pow(10, Math.max(aDecimals, bDecimals))
const aInt = Math.round(a * factor) const bInt = Math.round(b * factor)
switch (operation) { case '+': return (aInt + bInt) / factor case '-': return (aInt - bInt) / factor case '*': return (aInt * bInt) / (factor * factor) case '/': return aInt / bInt default: throw new Error('Unknown operation') }}数字格式化#
// 千分位分隔function formatNumber(num) { return num.toLocaleString('zh-CN')}formatNumber(1234567.89) // '1,234,567.89'
// 保留指定小数位function toFixed(num, decimals) { const factor = Math.pow(10, decimals) return Math.round(num * factor) / factor}toFixed(3.14159, 2) // 3.14
// 百分比function toPercent(num, decimals = 2) { return (num * 100).toFixed(decimals) + '%'}toPercent(0.1234) // '12.34%'范围限制#
function clamp(value, min, max) { return Math.min(Math.max(value, min), max)}
clamp(5, 0, 10) // 5clamp(-5, 0, 10) // 0clamp(15, 0, 10) // 10
// 实际应用:滑块值、音量控制等随机数#
// 指定范围的整数function randomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min}
// 随机数组元素function randomItem(arr) { return arr[randomInt(0, arr.length - 1)]}
// 生成随机 IDfunction randomId(length = 8) { const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' return Array.from({ length }, () => randomItem(chars.split(''))).join('')}小结#
| 类别 | 新增内容 |
|---|---|
| 字面量 | 0b(二进制)、0o(八进制)、_(分隔符) |
| Number 属性 | EPSILON、MAX_SAFE_INTEGER、MIN_SAFE_INTEGER |
| Number 方法 | isFinite、isNaN、isInteger、isSafeInteger、parseInt、parseFloat |
| Math 方法 | trunc、sign、cbrt、clz32、imul、fround、hypot、expm1、log1p、log10、log2 |
这些扩展让数值处理更加精确和便捷,特别是在处理精度敏感的金融计算时,要格外注意浮点数的精度问题。