开发过程中踩过的坑

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。打开,可以不用解压,能找到需要的文件。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值