06.数值的扩展

    科技2025-01-15  3

    1.二进制和八进制表示法

    ES6提供二进制和八进制的新写法: 二进制:0b(或0B);八进制:0o(或0O); // 二进制:0b/0B let res1 = (0b111110111 === 503); console.log(res1); // true // 八进制:0o/0O let res2 = (0o767 === 503); console.log(res2); // true ES5开始,严格模式下八进制数不允许使用前缀0表示; // 严格模式下,不允许使用0前缀表示八进制数,需要用0o形式的前缀 // 非严格模式 (function () { console.log(0o11 === 011); // true })() // 严格模式下 (function () { "use strict" console.log(0o11 === 011); // Octal literals are not allowed in strict mode. })() 转换为十进制数:使用Number()方法; // 转换为十进制数:使用number()方法 console.log(Number(0b111)); // 7 console.log(Number(0o111)); // 73 console.log(Number(0x111)); // 23

    2.Number.isFinite()、Number.isNaN()

    Number.isFinite():用于检查一个数值是否为有限的; Number.isFinite(1); // true ES5中可以用下列代码部署该方法: // ES5中部署Number.isFinite()方法的代码 (function (global) { // 这里没太看懂 var global_isFinite = global.isFinite; // 自定义Number对象的isFinite属性 Object.defineProperty(Number,'isFinite',{ value : function (value) { return typeof value === 'number' && global_isFinite(value); }, configurable : true, enumerable :false, writable : true }) })(this); Number.isNaN():用来检查一个值是否为NaN;非NaN数值一律返回false; Number.isNaN(NaN); // true ES5中可以用下列代码部署该方法: // ES5中部署Number.isNaN()方法的代码 (function (global) { // 这里没太看懂 var global_isNaN = global.isNaN; // 自定义Number对象的isFinite属性 Object.defineProperty(Number,'isNaN',{ value : function (value) { return typeof value === 'number' && global_isNaN(value); }, configurable : true, enumerable :false, writable : true }) })(this);

    3.parseInt()和parseFloat()方法

    ES6将这两个方法移植到了Number对象上面,行为与原先保持一致;这么做的目的是在于逐步减少全局性方法,使得JavaScript逐步模块化; // ES6将这两个全局方法移植到了Number对象上 // ES5的写法 let res1 = parseInt("1.11"); // 1 let res2 = parseFloat("123.886#"); // 123.886 // ES6的写法 let res3 = Number.parseInt("1.111111"); // 1 let res4 = Number.parseFloat("12.12#@$"); // 12.12

    4.Number.isInteger()方法

    作用:判断一个值是否为整数;在JavaScript内部,整数和浮点数是同样的存储方法,因此1和1.0被看做是同一个值;ES5中部署该方法的代码见p88; // 该方法用于判断一个数是否是整数 let res1 = Number.isInteger(12.0); // true let res2 = Number.isInteger(12); // true

    5.Number.EPSILON

    ES6新增的一个极小的常量;引入该常量的目的:为浮点数计算设置一个误差范围;如果误差小于这个常量就可以认为得到的是正确的浮点数运算结果;该常量的实质其实是一个可以接受的误差范围; // Number.EPSILON 一个常量 用于设置误差范围 const res1 = Number.EPSILON; console.log(res1.toFixed(30)); // 0.000000000000000222044604925031 // 例子 误差检查函数 function withinErrorMargin(left,right){ return Math.abs(right - left) < Number.EPSILON; // 计算结果与计算结果的目标值之差的绝对值与该常量 比较 } console.log(withinErrorMargin(0.1 + 0.2 , 0.3)); // true console.log(withinErrorMargin(0.1 + 0.3 , 0.3)); // false

    6.安全整数和Number.isSafeInteger()

    安全整数

    JavaScript中能表示的整数范围在正2的53次方到负2的53次方之间,超出这个范围就无法精确表示;

    Number.MAX_SAFE_INTEGER 和 Number.MIN_SAFE_INTEGER

    用于表示安全整数这个范围的上下限; // Number.MAX_SAFE_INTEGER 和 Number.MIN_SAFE_INTEGER 表示安全整数范围的上下限 let res1 = Number.MAX_SAFE_INTEGER; // 9007199254740991 let res2 = Number.MIN_SAFE_INTEGER; // -9007199254740991

    Number.isSafeInteger()方法

    用于检测一个整数是否在安全整数的范围内(处于安全范围内的整数返回true,其他数据类型以及范围外的数据都返回false); // Number.isSafeInteger() 用于检测整数是否在安全整数的范围内 let res3 = Number.isSafeInteger(Number.MAX_SAFE_INTEGER); // true let res4 = Number.isSafeInteger(Number.MAX_SAFE_INTEGER + 1); // false

    Number.isSafeInteger()方法实现原理

    原理:仅需要将整数与范围边界作比较即可; // Number.isSafeInteger()方法原理 function isSafeInteger(num) { return (typeof num === "number" && Math.round(num) === num && Number.MAX_SAFE_INTEGER >= num && Number.MIN_SAFE_INTEGER <= num); } console.log(isSafeInteger(1)); // true console.log(isSafeInteger(Number.MAX_SAFE_INTEGER + 1)); // false 在实际使用该方法时,不仅仅需要检测最后的运算结果是否在安全整数范围内,同时也需要检测所有参与运算的整数;检测两个运算数与结果的列子: function trusty(left,right,result){ /* left:参与运算的第一个整数 right:参与运算的第二个整数 result:运算结果 */ if(Number.isSafeInteger(left) && Number.isSafeInteger(right) && Number.isSafeInteger(result)){ return result; } throw new RangeError("某一数值不在安全范围内!"); } console.log(trusty(1,2,3)); // 3

    7.Math对象的扩展

    ES6为Math新增了17个与数学相关的静态方法,只能在Math对象上调用;

    Math.trunc()

    用于去除小数部分,返回一个整数;关于参数: 非数值:先转换为Number类型;空值和无法截取整数的值:返回NaN; // 1. Math.trunc() 去掉小数,返回一个整数 let res1 = Math.trunc(12.1212); // 12 let res2 = Math.trunc("123.321"); // 123 字符串先转换为Number let res3 = Math.trunc(); // NaN 对于未部署Math.trunc()方法的环境,可以使用以下代码模拟: // 兼容不支持ES6语法的浏览器 Math.trunc = Math.trunc || function(x){ // < 0 : 向上取整 > 0 向下取整 return x < 0 ? Math.ceil(x) : Math.floor(x); }

    Math.sign()

    用于判断一个数是正数、负数、还是零;非数值会先转换为Number类型;返回值为以下有4种类型中的一个: 参数为正数:+1;参数为负数:-1;参数为0:0;参数为-0:0;参数为其他值:NaN; // 2.Math.sign 方法:判断一个数是正数、负数、还是0 // 正数 let res4 = Math.sign(12); // 1 // 负数 let res5 = Math.sign(-12); // -1 // 0 let res6 = Math.sign(0); // 0 // -0 let res7 = Math.sign(-0); // 0 // NaN let res8 = Math.sign(NaN); // NaN 对于未部署ES6的环境,可以用以下方法模拟: // ES5语法模拟Math.sign()方法 Math.sign = Math.sign || function (x) { x = +x; // 转换为数值 if(x === 0 || Math.isNaN(X)){ return x; } return x > 0 ? 1 : -1; }

    Math.cbrt()

    该方法用于计算一个数的立方根; // Math.cbrt() 计算立方根 let re1 = Math.cbrt(8); // 2 let re2 = Math.cbrt("test"); //NaN 对于未实现ES6语法的环境,可用以下方法来模拟: // ES5模拟Math.cbrt()方法 Math.cbrt = Math.cbrt || function (x) { return Math.pow(Math.abs(x),1/3); // Math.pow(a,b):返回a的b次幂结果 }

    Math.clz32()

    将参数转为 32 位无符号整数的形式,然后返回这个 32 位值里面有多少个前导 0; // 4.Math.clz32() 将参数转换为32位二进制,并返回前补0的个数 let re3 = Math.clz32(1); // 31 对于小数,Math.clz32()只考虑整数部分; // 对于小数 只考虑整数部分 let re4 = Math.clz32(1.22); // 31 左移运算符与Math.clz32()方法直接相关(左移运算能改变前补0的个数): // 左移运算符与该方法的关系 let re5 = Math.clz32(1 << 1); // 30 空值和其他类型:先转换为Number类型;

    Math.imul()

    作用:返回两个数以32位带符号整数形式相乘的结果,返回的结果也是带符号的32位整数形式;该方法等同于a*b的形式,但是为什么还需要Math.imul()方法? 因为JavaScript有精度限制,超过正负2的53次方的数值就无法精确表示,因此对于很大位数的乘法,其低位数值往往都是不准确的;使用Math.imul()方法可以返回正确的低位数值; // Math.imul() 求两个数32位无符号整数形式之积 并返回32位无符号整数形式的结果 let re1 = Math.imul(0x7fffffff, 0x7fffffff); // 1

    Math.fround()

    作用:返回一个数的单精度浮点数形式;

    Math.hypot()

    返回所有参数的平方和的平方根;

    对数方法

    Math.expm1()

    Math.expm1(x)返回 ex - 1,即Math.exp(x) - 1;

    Math.log1p()

    Math.log1p(x)方法返回1 + x的自然对数,即Math.log(1 + x)。如果x小于-1,返回NaN。

    Math.log10()

    Math.log10(x)返回以 10 为底的x的对数。如果x小于 0,则返回 NaN;

    Math.log2()

    Math.log2(x)返回以 2 为底的x的对数。如果x小于 0,则返回 NaN。

    双曲函数方法

    Math.sinh(x) 返回x的双曲正弦(hyperbolic sine)Math.cosh(x) 返回x的双曲余弦(hyperbolic cosine)Math.tanh(x) 返回x的双曲正切(hyperbolic tangent)Math.asinh(x) 返回x的反双曲正弦(inverse hyperbolic sine)Math.acosh(x) 返回x的反双曲余弦(inverse hyperbolic cosine)Math.atanh(x) 返回x的反双曲正切(inverse hyperbolic tangent)

    8.指数运算符

    写法:**a**b:表示a的b次方; a **= a;//等于 a=a*a a ***= a;//等于 a=a*a*a

    10.BigInt数据类型

    JavaScript 所有数字都保存成 64 位浮点数,这给数值的表示带来了两大限制。一是数值的精度只能到53个二进制位(相当于16个十进制位),大于这个范围的整数,JavaScript是无法精确表示的,这使得JavaScript不适合进行科学和金融方面的精确计算。二是大于或等于2的1024次方的数值,JavaScript 无法表示,会返回Infinity。用来表示整数,没有位数的限制,任何位数的整数都能精确表示; // BigInt 用来表示整数,没有位数限制,因此能精确表示任何位数 const a = 2172141653n; const b = 15346349309n; // BigInt 可以保持精度 a * b // 33334444555566667777n // 普通整数无法保持精度 Number(a) * Number(b) // 33334444555566670000 为了与Number类型区分,BigInt类型需要加后缀n; // BigInt类型需要加后缀n // 普通数字 1n + 2n; // 3n // 各种进制表示 0b1101n // 二进制 0o777n // 八进制 0xFFn // 十六进制 BigInt类型与普通整数是两种值,两者并不相等; // BigInt类型与普通整数是两种值,两者并不相等 (1n === 1); // false typeof对BingInt返回bigint; // typeof对BingInt返回bigint (typeof 1n); // bigint BinInt可以使用-号,但是不可以使用+号,会与asm.js冲突; -42n // 正确 +42n // 报错

    BigInt对象

    JavaScript 原生提供BigInt对象,可以用作构造函数生成 BigInt 类型的数值。转换规则基本与Number()一致,将其他类型的值转为 BigInt; BigInt(123);// 123n BigInt("123"); // 123n BigInt(true); // 1n BigInt(false); // 0n BigInt构造函数在使用时,必须有参数,且参数必须要可以转换为数值,否则会报错(如null、undefined等);参数不可以是小数;

    BigInt提供的方法

    继承了Object对象的两个方法:

    BigInt.prototype.toString()BigInt.prototype.valueOf()

    继承了Number对象的一个实例方法:

    BigInt.prototype.toLocaleString()

    自身提供三个静态方法:

    BigInt.asUintN(width, BigInt): 给定的 BigInt 转为 0 到 2width - 1 之间对应的值。BigInt.asIntN(width, BigInt):给定的 BigInt 转为 -2width - 1 到 2width - 1 - 1 之间对应的值。BigInt.parseInt(string[, radix]):近似于Number.parseInt(),将一个字符串转换成指定进制的 BigInt。

    转换规则:可以使用Boolean()、Number()和String()这三个方法,将 BigInt 可以转为布尔值、数值和字符串类型。

    数学运算:

    除了不带运算符的右移位运算符(>>>)和一元求和运算符(+),其他的都可以用;不能与普通数值混合运算;
    Processed: 0.010, SQL: 8