工作中,几乎习惯了大量使用方便的工具库(如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. BZOJ 3754 Tree之最小方差树 MST

    Description Wayne 在玩儿一个很有趣的游戏.在游戏中,Wayne 建造了N 个城市,现在他想在这些城市间修一些公路,当然并不是任意两个城市间都能修,为了道路系统的美观,一共只有M 对城 ...

  2. [K/3Cloud] 创建一个操作校验器

    概念: 定义了一个校验器对象,通常是添加到业务单据操作服务插件,用于对操作的合法性进行校验.继承自校验器抽象对象AbstractValidator. 示例: 新建一个类,继承自AbstractVali ...

  3. linux下crontab安装和使用(定时任务)

    在Unix和Linux的操作系统之中,cron可以让系统在指定的时间,去执行某个指定的任务,crontab命令常用于管理对应的cron. 一.crontab在线安装 yum -y install vi ...

  4. 洛谷 P1318 积水面积

    P1318 积水面积 题目描述 一组正整数,分别表示由正方体迭起的柱子的高度.若某高度值为x,表示由x个正立方的方块迭起(如下图,0<=x<=5000).找出所有可能积水的地方(图中蓝色部 ...

  5. Ubuntu 16.04 GNOME下解决Sublime Text3中文输入(ibus)(转)

    解决方法: 1.进入Sublime Text3插件管理文件夹 cd ~/.config/sublime-text-3/Packages 2.获取InputHelper插件 git clone http ...

  6. Nginx+Tomcat+Memcached负载均衡和session共享

    1. 演示搭建 说明:本文参考网络日志http://blog.csdn.net/remote_roamer/article/details/51133790,结合实际操作,仅做个演示记录. 1.1.  ...

  7. Mac使用技巧之Finder的个人收藏

    当使Finder的时候,左側会列出来个人收藏,能够非常方便的打开对应的文件夹.那么怎样把自己新建的文件夹也增加到个人收藏呢? 1.默认的个人收藏 2.新建名字为my_ios_demo文件夹,拖动这个文 ...

  8. linux网络结构体

    一 链路层: (1)局域网(以太网ethernet): *struct eth_header:以太网头部. (ethernet/eth.c) *struct net_device:每一个网络设备都用这 ...

  9. 查看yarn当前执行任务列表

    Author: kwu 查看yarn当前执行任务列表.可使用例如以下命令查看: yarn application -list 如需杀死当前某个作业,使用kill application-id的命令例如 ...

  10. ORA-00907: 缺失右括号(通用解决办法)

    PL/SQL 的SQL语句可以执行,但是放在hibernate中,后台打印,出现了错误. 错误的SQL解析:黄色为错误部分 Hibernate:      select         examine ...