229

さて、私はparseIntをいじって、まだ初期化されていない値をどのように処理するかを確認し、この宝石に出くわしました。以下は、基数24以上で発生します。

parseInt(null, 24) === 23 // evaluates to true

IE、Chrome、Firefoxでテストしましたが、すべてtrueと警告されているので、仕様のどこかにあるはずだと思います。グーグルですばやく検索しても結果が得られなかったので、誰かが説明してくれることを願っています。

typeof null === "object"オブジェクトとヌルがメモリ内またはそれらの線に沿った何かにほぼ同一のタイプ識別子を持つ原因となった見落としのために彼が言っていたクロックフォードのスピーチを聞いたのを覚えていますが、今はそのビデオを見つけることができません。

試してみてください:http://jsfiddle.net/robert/txjwP/

編集修正:基数が高いほど異なる結果が返され、32は785077が返されます
編集2 zzzzBovから:[24...30]:23, 31:714695, 32:785077, 33:859935, 34:939407, 35:1023631, 36:1112745


tl; dr

なぜparseInt(null, 24) === 23本当の声明なのか説明してください。

4

6 に答える 6

243

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
于 2011-06-23T20:03:06.113 に答える
119

Mozillaは次のように伝えています。

関数 parseIntは、最初の引数を文字列に変換して解析し、整数または NaN を返します。NaN でない場合、返される値は、指定された基数 (基数) の数値として取得された最初の引数の 10 進整数表現になります。たとえば、基数 10 は 10 進数から変換することを示し、8 は 8 進数、16 は 16 進数などです。10 より大きい基数の場合、アルファベットの文字は 9 より大きい数字を示します。たとえば、16 進数 (基数 16) の場合、A から F が使用されます。

仕様では、15.1.2.2 ToString/1は、文字列への変換が組み込みの を使用して実行"null"されることtoStringを示してい"[object Window]"ます。

では、考えてみましょうparseInt("null", 24)

もちろん、これは完全に base-24 の数値文字列ではありませんが、「n」は10 進数の 23です。

これで、base-24 システムには見つから"u" ないため、10 進数の 23 が引き出された後に解析が停止します。

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

parseInt(null, 23)(そして、これが(およびより低い基数) がNaN23 ではなく 23を返す理由です:"n"は base-23 システムにありません。)

于 2011-06-23T20:03:01.620 に答える
79

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(基数)とします。
  • stripPrefixをtrueにします。
  • R≠0の場合、a。R<2またはR>36の場合、NaNを返します。b。R≠16の場合、stripPrefixをfalseにします。
  • それ以外の場合、R =0a。R=10とします。
  • stripPrefixがtrueの場合、a。Sの長さが2以上で、Sの最初の2文字が「0x」または「0X」の場合は、Sから最初の2文字を削除し、R=16とします。
  • Sに基数Rの数字ではない文字が含まれている場合、Zを最初のそのような文字の前のすべての文字で構成されるSの部分文字列とします。それ以外の場合は、ZをSとします。
  • Zが空の場合は、NaNを返します。
  • mathIntを基数R表記のZで表される数学整数値とし、値が10〜35の数字にAZとazの文字を使用します(ただし、Rが10で、Zに20を超える有効桁数が含まれる場合、すべての有効値は20番目以降の桁は、実装のオプションで0桁に置き換えることができます。また、Rが2、4、8、10、16、または32でない場合、mathIntは実装に依存する数学整数の近似値になります。基数-R表記のZで表される値。)
  • numberをmathIntのNumber値とします。
  • 戻り記号×数字。

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

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

ここに画像の説明を入力してください

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)です。:)

いずれにせよ、素晴らしい質問です!

于 2011-06-23T20:17:34.280 に答える
34
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 とします。

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

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

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

QED

于 2011-06-23T20:04:39.993 に答える
16

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

于 2011-06-23T20:03:37.607 に答える
7

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

parseInt("n",24) -> 23

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

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

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

于 2011-06-23T20:06:45.813 に答える