web-dev-qa-db-ja.com

parseInt(null、24)=== 23 ...待って、何?

さて、私はparseIntをいじって、まだ初期化されていない値をどのように処理するかを見ていたので、このgemを見つけました。以下は、基数24以上で発生します。

_parseInt(null, 24) === 23 // evaluates to true
_

IEでテストしました、ChromeおよびFirefoxで、すべてが真であるため、どこかの仕様に含まれている必要があると考えています。私は誰かが説明できることを望んでいます。

Object and Nullがメモリまたはそれらの行に沿った何かにほぼ同一のタイプ識別子を持っているために、彼が_typeof null === "object"_と言っていたCrockfordのスピーチを聞いたことを覚えていますが、私は今そのビデオを見つけることができません。

それを試してください: http://jsfiddle.net/robert/txjwP/

Edit修正:基数を大きくすると異なる結果が返され、32では785077が返されます
Edit 2zzzzBovから:_[24...30]:23, 31:714695, 32:785077, 33:859935, 34:939407, 35:1023631, 36:1112745_


tl; dr

parseInt(null, 24) === 23が真のステートメントである理由を説明してください。

225
Robert

nullを文字列"null"に変換し、変換しようとしています。基数0〜23の場合、変換できる数字がないため、NaNを返します。 24では、"n"(14番目の文字)が数字システムに追加されます。 31では、"u"(21文字目)が追加され、文字列全体をデコードできます。 37では、生成できる有効な数値セットがなくなり、NaNが返されます。

js> parseInt(null, 36)
1112745

>>> reduce(lambda x, y: x * 36 + y, [(string.digits + string.lowercase).index(x) for x in 'null'])
1112745
237

Ignacio Vazquez-Abramsは正しいですが、 仕組み ...

15.1.2.2 parseInt (string , radix)から:

ParseInt関数が呼び出されると、次の手順が実行されます。

  • inputStringをToString(string)にします。
  • Sを、StrWhiteSpaceCharではない最初の文字と、その文字に続くすべての文字で構成されるinputStringの新しく作成されたサブストリングとします。 (つまり、先頭の空白を削除します。)
  • 符号を1にします。
  • Sが空でなく、Sの最初の文字がマイナス記号-である場合、符号を-1にします。
  • Sが空ではなく、Sの最初の文字がプラス記号+またはマイナス記号-である場合、Sから最初の文字を削除します。
  • R = ToInt32(radix)とします。
  • StripPrefixをtrueにします。
  • R≠0の場合、a。 R <2またはR> 36の場合、NaNを返します。 b。 R≠16の場合、stripPrefixをfalseにします。
  • そうでない場合、R = 0 a。 R = 10とする。
  • StripPrefixがtrueの場合、a。 Sの長さが少なくとも2で、Sの最初の2文字が「0x」または「0X」の場合、Sから最初の2文字を削除し、R = 16にします。
  • Sが基数R以外の文字を含む場合、Zを最初のそのような文字の前のすべての文字で構成されるSの部分文字列とします。それ以外の場合は、ZをSにします。
  • Zが空の場合、NaNを返します。
  • MathIntを、10〜35の値を持つ数字にA〜Zおよびa〜zの文字を使用して、基数R表記でZで表される数学的な整数値とします。実装のオプションで、20番目以降の数字を0桁に置き換えることができ、Rが2、4、8、10、16、または32でない場合、mathIntは数学的な整数の実装依存の近似値になることがあります基数R表記のZで表される値。)
  • NumberをmathIntのNumber値とします。
  • 符号×数値を返します。

注parseIntは、文字列の先頭部分のみを整数値として解釈する場合があります。整数の表記の一部として解釈できない文字は無視され、そのような文字が無視されたという表示はありません。

ここには2つの重要な部分があります。両方とも太字にしました。まず最初に、toStringnull表現が何であるかを知る必要があります。その情報については、セクション9.8.0の_Table 13 — ToString Conversions_を確認する必要があります。

enter image description here

すばらしいので、toString(null)を内部で実行すると_'null'_文字列が生成されることがわかりました。素晴らしいですが、指定された基数内では無効な数字(文字)をどのように正確に処理しますか?

上記の_15.1.2.2_を見ると、次のコメントが表示されます。

Sに基数R以外の文字が含まれている場合、Zを最初のそのような文字の前のすべての文字で構成されるSの部分文字列とします。それ以外の場合は、ZをSにします。

つまり、指定された基数の前にすべての数字を処理し、他のすべてを無視します。

基本的に、parseInt(null, 23)を実行することはparseInt('null', 23)と同じことです。 uにより、2つのlが無視されます(基数23の一部である場合でも)。したがって、解析できるのはnのみであり、ステートメント全体がparseInt('n', 23)と同義になります。 :)

どちらにしても、素晴らしい質問です!

79
David Titarenco
parseInt( null, 24 ) === 23

と同等です

parseInt( String(null), 24 ) === 23

これは

parseInt( "null", 24 ) === 23

基数24の数字は、0、1、2、3、4、5、6、7、8、9、a、b、c、d、e、f、...、nです。

言語仕様には

  1. Sに基数Rの数字以外の文字が含まれている場合、Zを最初のそのような文字の前のすべての文字で構成されるSの部分文字列とします。それ以外の場合は、ZをSにします。

これは、15LのようなCスタイルの整数リテラルが適切に解析されることを保証する部分です。したがって、上記は

parseInt( "n", 24 ) === 23

"n"は、上記の数字リストの23文字目です。

Q.E.D.

33
Mike Samuel

nullは文字列"null"に変換されると思います。したがって、nは実際には 'base24'の23( 'base25' +と同じ)、uは 'base24'で無効なので、残りの文字列nullは無視されます。そのため、uが 'base31'で有効になるまで23を出力します。

16
Floern

parseIntは英数字表現を使用し、base-24では「n」は有効ですが、「u」は無効な文字であり、parseIntは値「n」のみを解析します。

parseInt("n",24) -> 23

例として、これを試してください:

alert(parseInt("3x", 24))

結果は「3」になります。

7
fdaines