【JS】温故知新: 从parseInt开始
工作中,几乎习惯了大量使用方便的工具库(如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开始的更多相关文章
- JS全局函数parseInt和parseFloat
1.parsetInt parseInt(string ,radix)解析一个字符串,并返回一个十进制的整数:该方法是将字符串转成十进制整数 console.log(parseInt("01 ...
- 理解Js的parseInt(转)
parseInt() 方法首先查看位置 0 处的字符,判断它是否是个有效数字:如果不是,该方法将返回 NaN,不再继续执行其他操作.但如果该字符是有效数字,该方法将查看位置 1 处的字符,进行同样的测 ...
- js中parseInt()与parseFloat(),Number(),Boolean(),String()转换
js将字符串转数值的方法主要有三种 转换函数.强制类型转换.利用js变量弱类型转换. 1. 转换函数: js提供了parseInt()和parseFloat()两个转换函数.前者把值转换成整数,后者把 ...
- JS 数据类型转换
JS 数据类型转换 方法主要有三种 转换函数.强制类型转换.利用js变量弱类型转换. 1. 转换函数: js提供了parseInt()和parseFloat()两个转换函数.前者把值转换成整数,后者把 ...
- js 字符串转换数字
方法主要有三种转换函数.强制类型转换.利用js变量弱类型转换. 1. 转换函数: js提供了parseInt()和parseFloat()两个转换函数.前者把值转换成整数,后者把值转换成浮点数.只有对 ...
- js 获取小数点位数方法及 字符串与数字之间相互转换方法
1.获取小数点位数方法 a. 使用 js 中 subsrting,indexOf,parseFloat三个函数,代码如下: var s = "22.127456" ;//s 为 字 ...
- js 字符串转换成数字的三种方法
在js读取文本框或者其它表单数据的时候获得的值是字符串类型的,例如两个文本框a和b,如果获得a的value值为11,b的value值为9 ,那么a.value要小于b.value,因为他们都是字符串形 ...
- js 字符串转换成数字(转)
转换函数: js提供了parseInt()和parseFloat()两个转换函数.前者把值转换成整数,后者把值转换成浮点数.只有对String类型调用这些方法,这两个函数才能正确运行:对其他类型返回的 ...
- js字符串转成数字的三种方法
js读取的html代码中获得的值 ,统统是以字符串的形式呈现的,为了方便我们后面对数据的操作,有时候我们有必要进行转换一下. 方法主要有三种 转换函数.强制类型转换.利用js变量弱类型转换. 1. 转 ...
随机推荐
- springData Jpa 快速入门
前言: 数据持久化的操作,一般都要由我们自己一步步的去编程实现,mybatis通过我们编写xml实现,hibernate也要配置对应的xml然后通过创建session执行crud操作.那么有没有这样一 ...
- Ubuntu 16.04 GNOME添加桌面图标/在桌面上显示图标
GNOME默认不能在桌面上创建文件夹,但是可以通过工具设置:用gnome-tweak-tool设置Nautilus接管桌面即可. 安装: sudo apt-get install gnome-twea ...
- 【.Net 学习系列】-- .Net 指定时间段内定时执行的Windows服务(System.Threading.Thread)
创建一个Windows服务项目:解决方案(右击)——> 添加 ——> 新建项目——>项目类型选择Windows——>模板选择Windows服务 ,如图: 编写Windows服务 ...
- [转] ASPNET Core 中获取应用程序物理路径
如果要得到传统的ASP.Net应用程序中的相对路径或虚拟路径对应的服务器物理路径,只需要使用使用Server.MapPath()方法来取得Asp.Net根目录的物理路径,如下所示: // Classi ...
- firewalld filter
实现 firewalld 的filter 功能 1. 关闭 INPUT ,关闭OUTPUT (设置黑名单) 任何主机 都 ping 不通 本主机 1>命令 : iptables -P INP ...
- 《转》 Ceilometer项目源代码分析----ceilometer项目源代码结构分析
感谢朋友支持本博客,欢迎共同探讨交流.因为能力和时间有限,错误之处在所难免,欢迎指正! 假设转载,请保留作者信息. 博客地址:http://blog.csdn.net/gaoxingnengjisua ...
- skype默认占用80和443port
今天把server的port更改为80,结果起不来,报告"port已经被占用"的错误. 使用下列命令找到了元凶: 1. netstat -ano | findstr 80 找到占用 ...
- Android小技巧总结1
0.Android彻底退出引用程序的方法 1) Dalvik VM的本地方法 android.os.Process.killProcess(android.os.Process.myPid()); / ...
- Codeforces Round #322 (Div. 2) D. Three Logos 模拟
D. Three Logos Three companies decided to order a ...
- 【bzoj1507】[NOI2003]Editor
第二次写rope了 rope大法好!!! #include<algorithm> #include<iostream> #include<ext/rope> #in ...