工作中,几乎习惯了大量使用方便的工具库(如underscore、lodash),但是长期的依赖,却有可能在我们注意不到的地方出现黑天鹅,笔者最近就碰到了这样一件例子:  

    parseInt(9e-10);

  本身是一句很简单的代码,只是把一个浮点数转换为整型,但是结果却出乎意料是9,所谓恶魔都藏在细节中,果不其然,parseInt的内部实现似乎并不是专门面向数字的。我们都知道parseInt有一些很有趣的特性:

  //去掉单位“px”
  let left = parseInt(YourDom.style.left);
//转换16进制数
  let hex = parseInt('ff', 16)

  但是,往往都忽略了为什么它会有这样的特性,于是笔者趁着周末适逢的大雨,饶有兴致的自己简单实现了一下parseInt:

let reg = /[^-\d]/;
let pureReg = /[^\d]/; function _slice(str, startIndex, endIndex){
if(endIndex > startIndex){
return str.slice(startIndex, endIndex);
}else{
return str;
}
} function $parseInt(val){
let _val = val; if(typeof(_val) !== 'string'){
_val = _val.toString();
} let strIndex = _val.match(reg) && _val.match(reg).index; if(strIndex == 0){
return NaN;
} let _str = _slice(_val, 0, strIndex); let negativeFlag = _str.indexOf('-') === 0 ? '-' : ''; if(negativeFlag){
_str = _str.slice(1);
} strIndex = _str.match(pureReg) && _str.match(pureReg).index;
_str = _slice(_str, 0, strIndex); return +(negativeFlag + _str);
}

  当然,笔者并没有实现原api中radix的相关功能,所以代码其实是比较少的,下面简单梳理下思路:

  首先,我们需要进行参数检测:   

   //如果参数的类型不为string和number,则调用它的toString方法,主要用于处理parseInt(Array)和parseInt(Number)的情况
if(typeof(_val) !== 'string'){
_val = _val.toString();
}

  这样,我们得到的就是一个字符串了,接着我们找到字符串中第一个不为整型数据应该具备的字符的位置,例如('9e-10'中,e就不应该是整型应该具备的字符),然后通过字符串的slice方法取出满足的部分(如上例中的'9')。

  接着,我们需要简单的处理下符号,毕竟整型包含正数和负数,规则其实和之前处理非法字符的思路是一致的: 

    //首先判断负号是否出现在最前面,是则将它取出来
let negativeFlag = _str.indexOf('-') === 0 ? '-' : ''; if(negativeFlag){
_str = _str.slice(1);
}
  //然后再剩余的字符串中寻找负号,按之前的策略处理
strIndex = _str.match(pureReg) && _str.match(pureReg).index;
_str = _slice(_str, 0, strIndex);

  然后,就可以得到一个parseInt方法了,笔者命名为$parseInt。

return +(negativeFlag + _str);

  其实,回过头来,parseInt这样非常简单的方法内部需要考虑的情况也是非常的多的,特别如果还有'.'和'+',情况则更为复杂,parseInt的场景中只有'-',反而还算是比较简单的,不过也正由于它的这种特性,对于浮点数的处理才会出现parseInt(9e-10)===9的奇怪现象,不过笔者仅是使用了几个例子反推的内部实现,究竟parseInt具体应该是怎么实现的,还需要翻看一下文档才能真正明确。

  随着前端圈的发展日趋完善,不断的框架、工具库层出不穷,常年居于顶层的我们可能都渐渐的远离了底层实现,但在某些具体的场景里,对这些底层实现的掌握,却有助于我们更好的处理好我们的日常工作,正如古人云“知其然,知其所以然”。其实,无论是工作,还是生活,保持一颗好奇心,我们的世界也会越来越大,越来越有意思。

  P.S.本文中的$parseInt仅基于以下几个例子实现,仅作抛砖引玉使用,并非parseInt的完整实现,请注意:

  

parseInt([1]); //1
parseInt(+0); //0
parseInt(-1); //-1
parseInt(123.123); //123
parseInt('-123-345');//-123

  

  

  

  

【JS】温故知新: 从parseInt开始的更多相关文章

  1. JS全局函数parseInt和parseFloat

    1.parsetInt parseInt(string ,radix)解析一个字符串,并返回一个十进制的整数:该方法是将字符串转成十进制整数 console.log(parseInt("01 ...

  2. 理解Js的parseInt(转)

    parseInt() 方法首先查看位置 0 处的字符,判断它是否是个有效数字:如果不是,该方法将返回 NaN,不再继续执行其他操作.但如果该字符是有效数字,该方法将查看位置 1 处的字符,进行同样的测 ...

  3. js中parseInt()与parseFloat(),Number(),Boolean(),String()转换

    js将字符串转数值的方法主要有三种 转换函数.强制类型转换.利用js变量弱类型转换. 1. 转换函数: js提供了parseInt()和parseFloat()两个转换函数.前者把值转换成整数,后者把 ...

  4. JS 数据类型转换

    JS 数据类型转换 方法主要有三种 转换函数.强制类型转换.利用js变量弱类型转换. 1. 转换函数: js提供了parseInt()和parseFloat()两个转换函数.前者把值转换成整数,后者把 ...

  5. js 字符串转换数字

    方法主要有三种转换函数.强制类型转换.利用js变量弱类型转换. 1. 转换函数: js提供了parseInt()和parseFloat()两个转换函数.前者把值转换成整数,后者把值转换成浮点数.只有对 ...

  6. js 获取小数点位数方法及 字符串与数字之间相互转换方法

    1.获取小数点位数方法 a. 使用 js 中 subsrting,indexOf,parseFloat三个函数,代码如下: var s = "22.127456" ;//s 为 字 ...

  7. js 字符串转换成数字的三种方法

    在js读取文本框或者其它表单数据的时候获得的值是字符串类型的,例如两个文本框a和b,如果获得a的value值为11,b的value值为9 ,那么a.value要小于b.value,因为他们都是字符串形 ...

  8. js 字符串转换成数字(转)

    转换函数: js提供了parseInt()和parseFloat()两个转换函数.前者把值转换成整数,后者把值转换成浮点数.只有对String类型调用这些方法,这两个函数才能正确运行:对其他类型返回的 ...

  9. js字符串转成数字的三种方法

    js读取的html代码中获得的值 ,统统是以字符串的形式呈现的,为了方便我们后面对数据的操作,有时候我们有必要进行转换一下. 方法主要有三种 转换函数.强制类型转换.利用js变量弱类型转换. 1. 转 ...

随机推荐

  1. 洛谷P1615 西游记公司

    题目背景 一道极其无厘头的题目 题目描述 事情是这样的:西游记中的孙沙猪(孙杀猪)三徒弟在西天取经之后开始进入厦门大学经贸系学习经济,在1个小时的学习后,他们用暴力手段毕业了.然后,他们创办了三个公司 ...

  2. [bzoj2251][2010BeiJing Wc]外星联络_后缀数组

    外星联络 bzoj-2251 2010-BeiJing Wc 题目大意:题目链接. 注释:略. 想法: 这咋做啊????一看数据范围才$3\cdot 10^3$. 建立后缀数组. 所以我们将所有后缀排 ...

  3. (入门SpringBoot)SpringBoot来临(一)

    .创建独立的Spring应用程序. .嵌入tomcat,Jetty或者Undertow,无需部署war文件; .允许通过Maven来获取starter; .尽可能的自动配置Spring. .提供生产就 ...

  4. 18.10.7 POIN 模拟赛

    期望 :80+ +90+40=210+ 实际 :30+90+0=120 链接:https://www.nowcoder.com/acm/contest/175/A来源:牛客网 时间限制:C/C++ 1 ...

  5. 【cocos2d-x 3.7 飞机大战】 决战南海I (三) 敌机实现

    如今来实现敌机类 敌机和我方飞机相似,具有生命值.能够发射子弹.而且有自己的运动轨迹.事实上能够为它们设计一个共同的基类,这样能够更方便扩展. 不同的敌机,应设置不同的标识.属性 // 敌机生命值 c ...

  6. Servlet学习笔记(八)—— 文件下载

    一.文件下载概述 比如图片或者HTML这类静态资源,仅仅要在浏览器中打开正确的网址就行下载.仅仅要资源放在应用程序文件夹或者其下的子文件夹中,但不在WEB-INF下.Servlet/JSP容器就会将资 ...

  7. Redis源代码分析(六)--- ziplist压缩列表

    ziplist和之前我解析过的adlist列表名字看上去的非常像.可是作用却全然不同.之前的adlist主要针对的是普通的数据链表操作. 而今天的ziplist指的是压缩链表.为什么叫压缩链表呢.由于 ...

  8. HDOJ 5387 Clock 水+模拟

    Clock Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Subm ...

  9. eclipse到Android Studio的项目迁移

    一直以来.公司开发都是用eclipse.可是随着我们应用不断成长.项目结构越来越庞大.项目间依赖关系变得非常复杂.用eclipse管理显得非常吃力,常常一个同事更改依赖项目之后,别人在更新.都会出现故 ...

  10. UVA 1397 - The Teacher's Side of Math(高斯消元)

    UVA 1397 - The Teacher's Side of Math 题目链接 题意:给定一个x=a1/m+b1/n.求原方程组 思路:因为m*n最多20,全部最高项仅仅有20.然后能够把每一个 ...