Code Fix

中級

['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.parseIntNumber にします。

この問題を解いてみる →

よくある誤解

parseIntを直接mapに渡せば数値に変換できると思いがちですが、mapが渡す3引数のうち2番目(インデックス)をparseIntは基数として解釈します。1番目の要素以降、意図しない基数で変換されます。

まとめ

['1','2','3'].map(parseInt)が[1, NaN, NaN]になる理由は中級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)