1 toFixed
toFixed() 方法可把 Number 四舍五入为指定小数位数的数字。
先来看几个例子:
const a2 = 0.0455;
const a3 = 0.0453;
const a4 = 0.044;
console.log(a2.toFixed(2)); // 0.05
console.log(a3.toFixed(2)); // 0.05
console.log(a4.toFixed(2)); // 0.04
方法返回正常结果,保留两位小数并且四舍五入。再来看下两个例子:
const a5 = 0.0450;
const a6 = 0.045;
const a7 = 0.0451;
const a8 = 0.046;
按照正常的理解,上面的变量保留两位小数都应该是0.05,实际结果:
console.log(a5.toFixed(2)); // 0.04
console.log(a6.toFixed(2)); // 0.04
console.log(a7.toFixed(2)); // 0.05
console.log(a8.toFixed(2)); // 0.05
注意:toFeixd在进位时如果需要进位的末尾是5,如果5后不存在或是0则不进位,否则进位。
遇到这样的问题可以使用lodash的round方法解决:
_.round(4.00655, 4);
// => 4.0066
_.round(4.006556, 4);
// => 4.0066
2 decodeURIComponent
自己写一个字符出,通过encodeURIComponent编码以后再通过decodeURIComponent解码,可以正常执行。
const url = 'http://www.baidu.com?a=jjj';
const urlEncode = encodeURIComponent(url);
console.log(decodeURIComponent(urlEncode)); // 'http://www.baidu.com?a=jjj'
但有时候需要解码的字符串并不是自己写的,比如通过后端返回字段获取的,如果书写不当在返回的url中有多余的“%”字符,什么是多余的呢?
console.log(urlEncode);
// http%3A%2F%2Fwww.baidu.com%3Fa%3Djjj
urlEncode中的"%"就是正常的,因为这些都是通过encodeURIComponent生产的,但是如果这样写再去解码
const url1 = 'http%3A%2F%2Fwww.baidu.com%3Fa%3Djjj%'; // 后面多了一个%
console.log(decodeURIComponent(url1));
控制台就会报错了,这个报错将会阻碍后面js代码的执行,可能会造成整个页面白屏。
所以在使用解码函数的时候,尽量使用tyr catch,防止意外发生。
try {
const url1 = 'http%3A%2F%2Fwww.baidu.com%3Fa%3Djjj%';
console.log(decodeURIComponent(url1));
} catch (error) {
}
3 地址栏url参数获取
const url = 'http://www.baidu.com?id=hjfd784932kjfdsa';
如果要获取url中拼接的参数,用字符串的拆分,一般都需要用到"="去获取等号两边的参数
举例:
function getUrlParams(url) {
const obj = {};
const str = url.split('?')[1].split('&');
for (let i = 0; i < str.length; i++) {
const a = str[i].split('=');
obj[a[0]] = a[1];
}
console.log(obj);
}</code></pre>
<p>但是有的时候Id是后端返回的,需要拼接到url传递到下一个页面。开发过程中遇到过一次后端返回的id是"jjfffytu888=843hfjsa"。这样的id处理起来就很麻烦了,上面获取url参数的方法将会完成失效。</p>
<p>测试一下:</p>
<pre><code class="language-js">const str = 'http://www.baidu.com?name=zhangsan&id=jjfffytu888=843hfjsa&age=18';
getUrlParams(str);
{
"name": "zhangsan",
"id": "jjfffytu888",
"age": "18"
}
遇到这样的情况有两种解决方案:
方案1: 用正则拆分字符串
function getUrlParams(str) {
str = str || window.location.href
if(typeof str !== 'string') return;
var params = {};
str.replace(/[?&]+([^=&]+)=([^&#]*)/gi, function(m,key,value) {
params[key] = value;
})
return params;
}
console.log(getUrlParams(str));
{
"name": "zhangsan",
"id": "jjfffytu888=843hfjsa",
"age": "18"
}
方案2:encodeURIComponent(id)去掉id中等号
const id = 'jjfffytu888=843';
console.log(encodeURIComponent(id)); // jjfffytu888%3D843
const idC = encodeURIComponent(id);
const str = `http://www.baidu.com?name=zhangsan&id=${idC}&age=18`;
获取到对应的参数后再解码:
decodeURIComponent(obj[id])
4 JS Number大数和精度问题
4.1 精度问题
人人都知道的一个坑:
0.1+0.2
0.30000000000000004
4.1.1 产生原因
JS中无论是小数还是整数,都只对应一种类型Number,采用 64 位双精度浮点数(但有效位数只有53位)。
64位比特分为三个部分:
- 正负数符号位S(sign)
- 指数位E
- 尾数位M
0.1 转成二进制表示为 0.0001100110011001100
(1100循环),由于尾数位的存储只有53位,所以转成的二进制会被截断为53位。
0.1 >> 0.0001 1001 1001 1001…(1001无限循环)
0.2 >> 0.0011 0011 0011 0011…(0011无限循环)
由于相加前的二进制都是被截断的,相加后,再转为10进制,误差也就应运而生了。
4.1.2 解决方案
扩大倍数相加然后再缩小相同倍数
const a = 0.1;
const b = 0.2;
const c = (a * 100 + b * 100) / 100;
console.log(c); // 0.3
decimal.js
import Decimal from 'decimal.js
const a = 0.1;
const b = 0.2;
// 加法
const c = new Decimal(a).add(new Decimal(b));
console.log(c.valueOf()); // '0.3'
// 减法
const d = new Decimal(a).sub(new Decimal(b));
console.log(d.valueOf()); // '-0.1'
// 乘法
const e = new Decimal(a).mul(new Decimal(b));
console.log(e.valueOf()); // '0.02'
// 除法
const f = new Decimal(a).div(new Decimal(b));
console.log(f.valueOf()); // '0.5'
4.2 大数问题
4.2.1 产生原因
因为Number类型的数据有效位只有53位 。所以js能表示的最大最小安全整数:
Number.MAX_SAFE_INTEGER
9007199254740991
Number.MIN_SAFE_INTEGER
-9007199254740991
也是就是
(-253 +1, 253 - 1)
(2^53, 2^54)
之间的数,只能精确表示偶数。
console.log(Math.pow(2, 53)); // 9007199254740992
console.log(Math.pow(2, 53) + 1); // 9007199254740992
console.log(Math.pow(2, 53) + 2); // 9007199254740994
console.log(Math.pow(2, 53) + 3); // 9007199254740996
console.log(Math.pow(2, 53) + 4);// 9007199254740996
4.2.3 解决方案
BIgint
BigInt
是一种内置对象,它提供了一种方法来表示大于 253 - 1
的整数。这原本是 Javascript中可以用。BigInt
可以表示任意大的整数。
typeof 1n === 'bigint'; // true
typeof BigInt('1') === 'bigint'; // true
const previousMaxSafe = BigInt(Number.MAX_SAFE_INTEGER);
// 9007199254740991n
const maxPlusOne = previousMaxSafe + 1n;
// 9007199254740992n
const theFuture = previousMaxSafe + 2n;
// 9007199254740993n, this works now!
const multi = previousMaxSafe * 2n;
// 18014398509481982n
const subtr = multi – 10n;
// 18014398509481972n
const mod = multi % 10n;
// 2n
const bigN = 2n ** 54n;
// 18014398509481984n
bigN * -1n
// –18014398509481984n
decimal.js
import Decimal from 'decimal.js
const b = 9007199254740993;
console.log(b); // 9007199254740992
// 加法
const c = new Decimal('9007199254740993');
console.log(c.valueOf()); // '9007199254740993'
注意:大数需要传入字符串才可以表示
5 excel导出问题
开发场景是有一个表格页面,需要导出excel文件。
导出其它格式没有啥问题,导出xlsx文件后,打开的过过程中报错。
遇到这样的问题解决方法如下:
点击是打开文件,然后ctrl+s另存为,这是就会弹出错误日志弹框:
点开弹框会看到错误信息所在的位置,然后排查代码看下是不是该位置导出的数据结构有问题。或者表头格式有问题。
xl/worksheets/sheet1xml文件所在的位置:
另存好的excel文件先关闭,然后修改后缀为.zip。打开,可以不用解压,能找到需要的文件。