发到网络上的极可能是这篇,javascript
编程是很抽象,很细致的一件事。java
正如difference
方法,有一层baseDifference
的抽象。drop方法,也有一个baseXXX
的方法(baseSlice)。编程
以base开头的函数,是一个基础的实现。一系列更具体的实现,都再这之上。浏览器
在这些基础或是具体的实现了,都不会缺乏一些帮助函数,在drop中一系列的实现中,就有以下的函数。网络
其实在drop
的实现源码里只有toInteger
。我将他们两个列出来是由于toInteger
基于toFinite,toNumber
, toNumber
中也有两个帮助函数函数
先看toNumber
这个函数的源码code
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原型上的一个方法,实际调用,返回的是它的实际值。ip
valueOf
返回指定对象的原始值。(primitive value )字符串
JavaScript的许多内置对象都重写了该函数,以实现更适合自身的功能须要。所以,不一样类型对象的valueOf()方法的返回值和返回值类型都可能不一样
作些尝试
var arr = [] arr.valueOf() == arr // => true var n = 1 n.valueOf() === n // => true var f = function(){} f.valueOf() === f // => true var d = new Date() d.valueOf() === d //false var b = true b.valueOf() === b // true var s = "123" s.valueOf() === s // true var 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
是十进制的前缀。
再回到以前代码的逻辑
+value
貌似没见过这种写法,查阅相关资料,(连接以下)
一元加号运算符,位于它要操做的数的前方,计算其操做数的数值,若是操做的value不是数字,也会尝试将它转换成数字。
一元正号是转换其余对象到数值的最快方法,也是最推荐的作法,由于它不会对数值执行任何多余操做。它能够将字符串转换成整数和浮点数形式,也能够转换非字符串值 true,false 和 null。小数和十六进制格式字符串也能够转换成数值。负数形式字符串也能够转换成数值(对于十六进制不适用)。若是它不能解析一个值,则计算结果为 NaN.
+3 // 3 +"3" // 3 +true // 1 +false // 0 +null // 0 +function(val){ return val;} //NaN
详细查看parseInt
方法,在没有指定基数
(传入的第二个参数,没有指定就是没传第二个参数),
freeParseInt(value.slice(2), isBinary ? 2 : 8)
这里其实就是根据输入的字符串是不是某进制开头作的判断,若是是8进制或2进制,就移除"字符串开头的0x",而后设置相应的进制。。。
如此麻烦的去作也是为了作兼容。
实际上,咱们使用parseInt的时候,应该明确的传入第二个参数。实际上,仍是应该尽可能使用_.toNumber
来规避这个问题。