發到網絡上的極可能是這篇,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
來規避這個問題。