博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
lodash源码乱读-drop后的故事(toNumber)
阅读量:5884 次
发布时间:2019-06-19

本文共 3092 字,大约阅读时间需要 10 分钟。

发到网络上的很可能是这篇,

编程是很抽象,很细致的一件事。

正如difference方法,有一层baseDifference的抽象。drop方法,也有一个baseXXX的方法(baseSlice)。

以base开头的函数,是一个基础的实现。一系列更具体的实现,都再这之上。

在这些基础或是具体的实现了,都不会缺少一些帮助函数,在drop中一系列的实现中,就有如下的函数。

  • toInteger
  • toFinite
  • toNumber

其实在drop的实现源码里只有toInteger。我将他们两个列出来是因为toInteger基于toFinite,toNumber, toNumber中也有两个帮助函数

  • isObject
  • isSymbol

先看toNumber这个函数的源码

function toNumber(value) {  if (typeof value == 'number') {    return value;  }  if (isSymbol(value)) {    return NAN;  }  if (isObject(value)) {    var other = typeof value.valueOf == 'function' ? value.valueOf() : value;    value = isObject(other) ? (other + '') : other;  }  if (typeof value != 'string') {    return value === 0 ? value : +value;  }  value = value.replace(reTrim, '');  var isBinary = reIsBinary.test(value);  return (isBinary || reIsOctal.test(value))    ? freeParseInt(value.slice(2), isBinary ? 2 : 8)    : (reIsBadHex.test(value) ? NAN : +value);}

我第一个疑惑的地方是这里

var other = typeof value.valueOf == 'function' ? value.valueOf() : value;

valueOf的理解只是知道它是Object原型上的一个方法,实际调用,返回的是它的实际值。

valueOf返回指定对象的原始值。(primitive value )

JavaScript的许多内置对象都重写了该函数,以实现更适合自身的功能需要。因此,不同类型对象的valueOf()方法的返回值和返回值类型均可能不同

做些尝试

var arr = []arr.valueOf() == arr // => truevar n = 1n.valueOf() === n// => truevar f = function(){}f.valueOf() === f// => truevar d = new Date()d.valueOf() === d  //falsevar b = trueb.valueOf() === b// truevar s = "123"s.valueOf() === s// truevar o = {a:1}o.valueOf() === o// true

只有Date类型有点奇怪,Date类型的valueOf返回的是存储的时间是从 1970 年 1 月 1 日午夜开始计的毫秒数 UTC。

之后是这里

value = isObject(other) ? (other + '') : other;

isObject

function isObject(value) {  var type = typeof value;  return value != null && (type == 'object' || type == 'function');}

需要排除null的影响。

value在这在做一个类型转换,转换撑字符串。

value = value.replace(reTrim, ''); //这里删除了 字符串的前后的空白符var isBinary = reIsBinary.test(value); // 二进制return (isBinary || reIsOctal.test(value)) //二进制或者八进制? freeParseInt(value.slice(2), isBinary ? 2 : 8): (reIsBadHex.test(value) ? NAN : +value);

要看懂上边的代码,要读懂下边的几个正则,

// 十六进制var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;// 二进制var reIsBinary = /^0b[01]+$/i;// 八进制var reIsOctal = /^0o[0-7]+$/i;

0x是十六进制的前缀,在计算机语言中,在数字前加进制前缀,更容易理解,必定同样的数字,同样是8进制或者二进制表示的真实数字天壤之别。

0b是二进制的前缀。

0o是八进制的前缀。

0d是十进制的前缀。

再回到之前代码的逻辑

  • 处理掉空白符
  • 保存二进制判断,因为有两处会用到
  • 二进制或者八进制判断
  • true => 截掉前缀并调用对应的parseInt返回结果
  • 如果是16进制,就返回NAN,否则返回value
+value

貌似没见过这种写法,查阅相关资料,(链接如下)

一元加号运算符,位于它要操作的数的前方,计算其操作数的数值,如果操作的value不是数字,也会尝试将它转换成数字。

一元正号是转换其他对象到数值的最快方法,也是最推荐的做法,因为它不会对数值执行任何多余操作。它可以将字符串转换成整数和浮点数形式,也可以转换非字符串值 true,false 和 null。小数和十六进制格式字符串也可以转换成数值。负数形式字符串也可以转换成数值(对于十六进制不适用)。如果它不能解析一个值,则计算结果为 NaN.

+3     // 3+"3"   // 3+true  // 1+false // 0+null  // 0+function(val){ return val;} //NaN

详细查看parseInt方法,在没有指定基数(传入的第二个参数,没有指定就是没传第二个参数),

  • 如果字符串 string 以"0x"或者"0X"开头, 则基数是16 (16进制).
  • 如果字符串 string 以"0"开头,基数是8(八进制)或者10(十进制),那么具体是哪个基数由实现环境决定。ECMAScript 5 规定使用10,但是并不是所有的浏览器都遵循这个规定。因此,永远都要明确给出radix参数的值。
  • 如果字符串 string 以其它任何值开头,则基数是10 (十进制)。
freeParseInt(value.slice(2), isBinary ? 2 : 8)

这里其实就是根据输入的字符串是否是某进制开头做的判断,如果是8进制或2进制,就移除"字符串开头的0x",然后设置相应的进制。。。

如此麻烦的去做也是为了做兼容。

实际上,我们使用parseInt的时候,应该明确的传入第二个参数。实际上,还是应该尽量使用_.toNumber来规避这个问题。

转载地址:http://lrlix.baihongyu.com/

你可能感兴趣的文章
jquery css3问卷答题卡翻页动画效果
查看>>
$digest already in progress 解决办法——续
查看>>
mysql 数据类型
查看>>
Ubuntu 设置当前用户sudo免密码
查看>>
ionic 调用手机的打电话功能
查看>>
怎么使用阿里云直播服务应用到现在主流直播平台中
查看>>
判断点是否在三角形内
查看>>
知行合一
查看>>
jmeter插件之jsonpath提取响应结果和做断言
查看>>
[Contiki系列论文之1]Contiki——为微传感器网络而生的轻量级的、灵活的操作系统...
查看>>
Android 网络编程 记录
查看>>
微软同步发行Windows 10和Windows 10 Mobile系统更新
查看>>
Zeppelin的入门使用系列之使用Zeppelin运行shell命令(二)
查看>>
form表单下的button按钮会自动提交表单的问题
查看>>
那些年追过的......写过的技术博客
查看>>
python基础教程_学习笔记19:标准库:一些最爱——集合、堆和双端队列
查看>>
CSS魔法堂:Transition就这么好玩
查看>>
C/C++ 多线程机制
查看>>
如何使用Core Text计算一段文本绘制在屏幕上之后的高度
查看>>
2010技术应用计划
查看>>