這是 ECMAScript 的老梗,但為什麼 Ramda 的 map()
就沒事呢 ?
Version
macOS Catalina 10.15.2
VS Code 1.40.2
Quokka 1.0.259
ECMAScript 2015
Ramda 0.26.1
map()
import { map } from 'ramda'
let data = ['1', '7', '11']
data.map(parseInt) // ?
map(parseInt)(data) // ?
同樣是將 parseInt()
傳進 map()
,但 ECMAScript 的 map()
與 Ramda 的 map()
竟然結果不同 ?
ECMAScript
Array.prototype.map()
arr.map(function callback( currentValue[, index[, array]]) { // return element for new_array }[, thisArg])
將 array 轉換成新 array
ECMAScript 的 callback 會回傳 3 個 argument:
currentValue
:目前 element 值index
:目前 index 值array
:完整 array
因此 map(parseInt)
依次會如下執行:
parseInt('1', 0, ['1', '7', '11']) // ?
parseInt('7', 1, ['1', '7', '11']) // ?
parseInt('11', 2, ['1', '7', '11']) // ?
已經可以發現 parseInt()
結果已經不如預期。
parseInt(string [, radix])
將 string 轉換成 int
其中第二個 argument 為 radix:
0
:自動改為10
1
:回傳NaN
2
~36
:radix 合理值37
以上:回傳NaN
因此 parseInt('1', 0)
為 10
,parseInt('7', 1)
為 NaN
,而 parseInt('11', 2)
為 3
。
至於第三個 argument 會自動忽略。
Ramda
map()
Functor f => (a → b) → f a → f b
將 array 轉換成新 array
重點在於 map()
的 callback 只有 (a -> b)
,因此 parseInt()
的第二個 argument 為 undefined
,所以 radix 為 10
,結果如預期沒有任何意外。
parseInt('1') // ?
parseInt('7') // ?
parseInt('11') // ?
parseInt()
如預期結果。
Conclusion
- 由於 ECMAScript
map()
的 callback 有 3 個 argument,都傳給parseInt()
造成不可預期結果;但 Ramda 的 callback 只有 1 個 argument,因此如預期 radix 為10
轉成 int
Reference
Eric Tong, Whe [‘1’, ‘7’, ‘11’].map(parseInt) return [1, NaN, 3] in JavaScript