前フリが思いつかない件について。
この記事の主旨は一言で言うと「parseIntには第2引数で基数を指定しよう」です。
基本
parseIntとparseFloatは、どちらも引数として渡された文字列をパースして数値に変換するグローバル関数。
parseIntは整数、parseFloatは小数と整数の両方(浮動小数点数)を扱える。
parseInt("100") // 100 parseInt("3.14") // 3 parseFloat("100") // 100 parseFloat("3.14") // 3.14
パース方法とNaN
parseIntとparseFloatは、どちらも引数の文字列を先頭から1文字ずつ確認し、数値と解釈できない文字が見つかった時点で、その直前までの部分を数値として返す。
一文字も数値にできなかった場合はNaN(数値ではないことを表す数値型の値)を返す。
わかりにくいので例を。
parseInt("100pt") // 100 parseInt("-3.14pt") // -3 parseInt("314e-2") // 314 parseInt("hoge123") // NaN parseFloat("100pt") // 100 parseFloat("-3.14pt") // -3.14 parseFloat("314e-2") // 3.14 parseFloat("hoge123") // NaN
parseFloatが数値と解釈できるのは、正負符号(+/-)、0〜9の数字、小数点、指数(e)。
parseIntはそこから小数点を除いたもの……ではなくて、実はもうちょっと複雑。
parseIntの第2引数(基数)
parseIntの引数として、パースしたい文字列のほかに、「何進数として解釈するか」という基数を渡すことができる。
基数は文字列でなくて数値で渡すことに注意。
parseInt("15", 10) // 15 parseInt("15", 8) // 13 parseInt("15", 16) // 21
同じ"15"という文字列を、10進数、8進数、16進数でパースした値が返ってくる。
基数の指定によって、数として解釈できる文字は変わってくる。ちょっと複雑と言ったのはこのこと。
parseInt("19e", 10) // 19("e"はパース不可) parseInt("19e", 8) // 1 ("9e"はパース不可) parseInt("19e", 16) // 414
基数を省略した場合、通常は10進数でパースされる。のだけど、省略するとけっこう危険だったりする。
基数を省略した場合
もしくは、基数に0を指定した場合、自動的に以下のように解釈されることが多い。
- "0x"または"0X"で始まる文字列が渡された場合、基数は16(16進数)と解釈される。
- "0"で始まる文字列が渡された場合、基数は8(8進数)と解釈される。
- その他の文字で始まる文字列が渡された場合、基数は10(10進数)と解釈される。
parseInt("0x15") // 21(16進数として解釈) parseInt("015") // 13(8進数として解釈)※実装による parseInt("15") // 15(10進数として解釈)
16進数はともかく、この8進数がなかなか厄介で……
parseInt("015") // 13(8進数)※実装による parseInt("019") // 1 (8進数、"9"はパース不可)※実装による parseInt("08") // 8 (8進数だとNaNになるので10進数で解釈)※実装による
あるでしょう、ノンブルとかで先頭をゼロで埋めてるやつ。
それをうっかりparseInt(textframe.contents)なんてやってしまうと、ページによって変な数値が返ってくる可能性があるということ。
余談
先頭の文字列が"0x"なら16進数、というのは、JavaScript(というか、ECMAScript)の仕様として規定されている。しかし実は先頭が"0"の場合は、「8進数にしてもいいよ(どっちかいうと10進数でやってね)」ということになっていた。
実装では8進数を採用したものが多いけど、確実ではないらしい。つまり実行する環境によって結果がまちまちということ。さっきから※実装によるって書いてるのはそういうことです。
いちおう現在の最新の仕様では、"0x"と"0X"を16進数とするのを除けばデフォルトは10進数、と定められている。けど実装のほうは今のところほとんど追いついてないらしい。AdobeのESTKでも8進数になるしね。
というわけで、この記事の主旨
「parseIntには第2引数で基数を指定しよう」
大事なことなので2回いいました。ちなみにparseFloatは常に10進数で、基数指定はできません。