有很多種方式可以將字串轉為數字。我能想到的方式就至少有5種!
1 2 3 4 5 6 7 8 9 |
parseInt(num); // 預設方式 (沒有基數) parseInt(num, 10); // parseInt 使用基數 (十進位制) parseFloat(num) // 浮點型 Number(num); // Number 建構函式 ~~num // 按位取反 num / 1 // 被 1 除 num * 1 // 被 1 乘 num - 0 // 減 0 +num // 一元操作 "+" |
該使用哪種方式?什麼時候?為什麼?這得分析每一種方式和使用它們時常見的陷阱。
根據 JsPerf.com 上的 benchmarks 一組測試表明,大多數瀏覽器都對 ParseInt 做過優化。雖然它可能是最快的一種方式,但是有可能會引起以下幾種錯誤:
1 2 |
parseInt('08') // 在一些老的瀏覽器裡會返回 0 parseInt('44.jpg') // 返回 44 |
parseInt:總是使用基數 = parseInt(num, 10);如果你不想讓它從字元裡面推斷數值,就不要使用它。
PareseFloat 又如何呢?它在不處理 16 進位制數字的時候,都發揮的很好;例子:
1 2 3 4 |
parseInt(-0xFF) // returns -255 parseInt("-0xFF") // returns -255 parseFloat(-0xFF) // returns -255 parseFloat("-0xFF") // returns 0 |
(注, 一個負 16 進位制數字符串是比較特殊的例子,當你在應用中解析它的時候,可能會導致意想不到的錯誤。 永遠記得在應用中檢查 NaN 值,以避免出現意外。)
另外, 當數字中含有字元時它會產生跟 parseInt 一樣的錯誤:
1 |
`parseFloat('44.jpg') // returns 44` |
**parseFloat: 處理 16 進位制數字的時候需要注意;如果你不想讓它從字元裡面推斷數值,就不要使用它。”
另外一種方法是 “按位取反” (~)。您僅可以使用它將字串轉換為整型,而不能轉為浮點型數字。它比較好的一面是,當碰到非數字字元的時候,它會返回 0。
1 2 3 4 |
~~1.23 // returns 1 ~~"1.23" // returns 1 ~~"23" // returns 23 ~~"Hello world" // returns 0 |
它做了什麼? 它 “翻轉” 了每一個二進位制位, 也被稱為 A1 補數。你可以使用它,但是也要意識到它只能處理成整數。所以,除非你確定數值的範圍在帶符號 32 位整型之內(因為在規範裡稱為 ToInt32),就不要使用它。
按位取反,使用的時候確保不存在非數字字元,只可用做整型轉換
Number 函式怎麼樣呢?當它解析的時候,會試圖從你給的字元中找出數字:
1 2 |
Number("023") // returns 23 Number(023) // returns 19 |
(注, 023 實際上是一個八進位制數。不管你做什麼,它都會返回 19;對於沒有引號的 16 進位制數來說,是一樣的)
Number 函式同樣也是 JsPerf 測試結果裡最慢的方法。
Number, 建議不要使用
最後一種方式:一元操作。
1 2 3 4 |
"1.23" * 1 // returns 1.23 "0xFF" - 0 // returns 255 "0xFF.jpg" / 1 // returns NaN +"023" // returns 23 |
不像其它方式,一元操作會在處理非數字時,丟擲一個 NaN
值。這也是我最喜歡的一種方式,因為一個字元不應該被考慮為 0 或者從它有多少位來猜測。大多數時候我會使用 +
操作,因為它是最不容易引起混亂的操作。不過一元操作並不是效能最好的一種方式 ——— 即使 -0
操作效能不錯。
字串轉數字最好的方式?
負 16 進位制數是唯一在字串中斷開的數字。其它的數字應首先解析成字串,然後通過一元操作或者帶有基數的 parseInt 來解析成數字。parseFloat 具有效能上的優勢,但是它會在相較於返回 NaN
更為合適的情況下返回一些數字。