JavaScriptで、何かを整数に変換するときに、いくつかの方法があります。foo
に値が入っているとして、
foo-0
+foo
parseFloat(foo)
Number(foo)
のようにして数値化したとすると、結果が違ってくるパターンはあるのでしょうか。
ToNumber
1、2、4については、内部で行われる変換にToNumber(仕様書9.3)という名前が付いています。中身としては、
- undefined→NaN
- nullとfalse→+0
- true→1
- 数値ならそのまま
- Objectは
valueOf
、そしてtoString
の順で変換を試み、得られたプリミティブを改めてToNumberにかける
文字列の場合(仕様書9.3.1)
文字列の場合は、前後のスペースを無視して、全体が
- 10進法の整数または小数
-
1.2e5
のような指数表記 -
0x
で始まる16進整数
のいずれかになれば、それを数値に変換します。一方、そうでなければNaNを返します。
なお、0を引き算しても、(-0という特殊な値を含めて)数値は変化しません(仕様書11.6.3)。つまり、上の1、2、4は、fooに何が入っていようが同じ結果となります。
parseFloatの中身
parseFloat
は、引数として文字列を取るのが前提なので、ToStringという内部操作(仕様書9.8)で文字列とした上で解釈します。なお、parseFloat
での解釈は上のToNumberとは違って、以下のようになっています(仕様書15.1.2.3)。
- 16進数を受け付けない。
- 数字以外のものが現れたら、そこより手前だけで評価する。
なお、ToStringの結果は、''.concat(foo)
で得ることができます1。
結果が違う場合
両者で結果が違う場合を下に挙げてみます。
- null、true、false…ToStringでそれぞれの文字列になるので、
parseFloat
の結果はNaNです。 - 16進文字列…最初の0だけが
parseFloat
に解釈されて、0を返します。 - 途中に別な文字が入っている文字列…
parseFloat
は別な文字の手前までを解釈しますが、ToNumberはNaNとします。 - 数値の-0…ToStringで'0'となってしまうので、
parseFloat
の結果は0を返します。 -
valueOf()
とtoString()
が違う結果を返すオブジェクト…標準のDate
がこんなオブジェクトです。
原典
JavaScriptのもととなっているECMAScriptの言語仕様については、Ecmaのサイトで公開されていますし、和訳版も書籍として入手可能です。
-
よく文字列化に
foo + ''
やString(foo)
が使われますが、これらはToString
と結果が一致しないことがあります。 ↩