['1','2','3'].map(parseInt)が[1, NaN, NaN]になる理由
Array.prototype.mapはコールバックに(要素, インデックス, 配列)の3引数を渡します。parseIntの第2引数は基数(何進数か)を表すため、インデックスがそのまま基数として渡されてしまいます。
なぜエラーが出ないのか
出力: [ 1, NaN, NaN ]
(エラーなし)- JavaScriptは何も報告しません。文法として正しいためです
出力: [ 1, NaN, NaN ]- 実際の挙動 — 期待した結果と食い違っている箇所
見つけ方- エラーが出ないので、出力を目で確かめるか、コードを目で追うしかありません。この種の誤りが最も発見が遅れます
このエラーが出る典型パターン
パターン1
1 const digits = ["1", "2", "3"]; 2 console.log(digits.map(parseInt )); ^
出力: [ 1, NaN, NaN ]期待: [ 1, 2, 3 ] (エラーにはなりません)
mapはコールバックに(要素, インデックス, 配列)を渡します。parseIntの第2引数は基数のため、インデックス1・2がそのまま基数として渡され、変換に失敗します。
直し方: parseInt を (v) => parseInt(v, 10) にします。
広告
広告スロット(未設定)
パターン2
1 const values = ["10", "20", "30"]; 2 console.log(values.map(parseInt )); ^
出力: [ 10, NaN, NaN ]期待: [ 10, 20, 30 ] (エラーにはなりません)
インデックス1が基数2、インデックス2が基数3として渡されるため、"20"や"30"は2進数・3進数としては変換できずNaNになります。
直し方: parseInt を (v) => parseInt(v, 10) にします。
パターン3
1 const values = ["4", "8", "12"]; 2 console.log(values.map(Number.parseInt)); ^
出力: [ 4, NaN, 1 ]期待: [ 4, 8, 12 ] (エラーにはなりません)
Number.parseIntも同じく第2引数を基数として扱うため、mapのインデックスをそのまま渡すと壊れます。Numberは余分な引数を無視するため安全です。
直し方: Number.parseInt を Number にします。
よくある誤解
parseIntを直接mapに渡せば数値に変換できると思いがちですが、mapが渡す3引数のうち2番目(インデックス)をparseIntは基数として解釈します。1番目の要素以降、意図しない基数で変換されます。
まとめ
['1','2','3'].map(parseInt)が[1, NaN, NaN]になる理由は中級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。