JavaScriptのparseIntの8進数の動作を回避するにはどうすればよいですか?


282

JavaScriptで以下を実行してみてください。

parseInt('01'); //equals 1
parseInt('02'); //equals 2
parseInt('03'); //equals 3
parseInt('04'); //equals 4
parseInt('05'); //equals 5
parseInt('06'); //equals 6
parseInt('07'); //equals 7
parseInt('08'); //equals 0 !!
parseInt('09'); //equals 0 !!

JavaScriptが先行ゼロが8進整数を示すと考える難しい方法を学んだところです。base -8 がない"8""9"、8であるので、関数はゼロを返します。好むと好まざるとにかかわらず、これは仕様によるものです

回避策は何ですか?

注:完全を期すために、私は解決策を投稿しようとしていますが、それは私が嫌う解決策なので、他の/より良い答えを投稿してください。


更新:

JavaScript標準の第5版(ECMA-262)では、この動作を排除する重大な変更が導入されています。Mozillaは良い記事を書いています。


21
ステップ1)好意を持ち、常に前の回答とDougの本で述べられているように基数を含めます。ステップ2)JavaScriptの学習に真剣に取り組んでいる場合は、Dougの本を自分で入手してください。それは非常に貴重です。これまでの私のお気に入りの本。:ここではFYIレビューですrealtech.burningbird.net/learning-javascript/basics/...
fuentesjr

8
Internet Explorer 9などのECMAScript 5th Edition互換ブラウザーでは、10解析する数値の前にが付いていない限り、基本パラメーターはデフォルトで(10進数)になります0x。たとえば0xFF、基本パラメーターはデフォルトで16になります。うまくいけば、1日、この問題遠い思い出になります。
アンディE

2
どう+'08' === 8ですか?ほんとだ!たぶんあなたは本当にparseIntあなたの本当のコードが必要ですが、上記のものは必要ありません。
kojiro

1
a)これはバグではありません。タイトルを修正してくださいb)Number('08')
OnTheFly

4
@portman:「第5版では...この動作を排除し、破断変更紹介」、実装がそれを行うにはない「奨励」されたとしても第3版では、そのうちの価値がポインティング(13年前)おそらくを:「基数があるとき0undefined文字列の数はで始まる0が続かない数字xX、実装は、その裁量で、オクタルあるとしてまたは小数であるとしてどちらかの番号を解釈することがあります。実装は10進数であるとして、この場合の数字を解釈することが奨励されています。(私の強調)
TJクラウダー

回答:


328

これは、簡単なソリューションでよくあるJavascriptの落とし穴です。

次のように、baseまたは 'radix'を指定するだけです。

parseInt('08',10); // 8

Numberを使用することもできます:

Number('08'); // 8

57
番号。輝かしい。
ポートマン、

10
Numberは08の前後に引用符が必要です。また警告されますが、Number('08 .123 ')は8.123を出力として生成します。本当に整数が必要な場合は、Numberを使用しないでください(または整数のみを確保するために入力をパターンマッチングします)。
Jason S

3
数値(08); FirefoxとIEで8をくれます。
Paolo Bergantino、

3
ECMAscript標準の一部ではありません。私はSpidermonkey 1.7(= Firefox JSエンジン)を使用するJSDBでテストしており、「08は正当なECMA-262 8進定数ではない」と不満を言う
Jason S

5
それでも、引用符には '08'を使用します。08はECMA-262標準に適合しておらず、警告やエラー、特定の動作、またはその両方がない場合の成功は保証されていません。
Jason S

43

値が符号付き32ビット整数の範囲になることがわかっている場合は~~x、すべてのシナリオで正しいことを行います。

~~"08" === 8
~~"foobar" === 0
~~(1.99) === 1
~~(-1.99)  === -1

~)ではなくバイナリを検索する場合、仕様では、引数に「ToInt32」変換が必要です。これは、Int32への明らかな変換を行い、NaN値をゼロに強制するように指定されています。

はい、これは信じられないほどハックですが、とても便利です...


2
1つのバイナリで十分なのに、なぜ2つの操作なのか?
Oleg

@オレグ、なぜ一人で十分でしょうか?
セバスチャン

3
@SebastianGodelet、| 0。
Oleg V. Volkov

@Grodriguez、| 0の0が文字列の場合
Oleg V. Volkov

この質問全体は、文字列を整数に変換するためのparseIntの代替案についてです。したがって:常に。
Grodriguez 2014年

24

parseIntのドキュメントから、オプションの基数引数を使用してbase-10を指定します。

parseInt('08', 10); //equals 8
parseInt('09', 10); //equals 9

これは、私を面倒で混乱し、冗長(実際には、すべてのparseIntに追加の引数がありますか?)と感じます。


6
冗長性が気に入らない場合は、組み込み関数を呼び出し、常に一定に保つ引数を埋める独自の関数を作成します。
Jason S

3
Stackiiiflowのすべての人が関数parseIntB10を作成することであなたを怒らせるようなわけではないので、Riiiiiiightはそうです。独自のラッパー関数を書くことは、この目的のためのひどい考えです。
ステファンケンドール

2
@iftrue:あなたは私のポイントを逃したと思います。私は個人的に、ベース10を強制するためにparseInt(someString、10)をどこでも実行することを気にしません。OPはこのアプローチを好きではないようです。ニーズ。(これは明らかにJQueryの背後にある考え方です。複雑さを追加することで便利にします。私はJQueryを使用しませんが、多くの人がそれを便利だと思っています。)
Jason S

4
実際にはそれがラップするために本当に重要だparseIntと同様に、関数式で便利な使用のためmap["7","4","09","5"].map(parseInt); Map合格するインデックスによって解釈される第二引数として配列の要素のをparseIntあなたはそれをラップしない限り、ベースとして。
Plynx 2013

11
function parseDecimal(s) { return parseInt(s, 10); }

編集:parseInt()呼び出しに常に「、10」を追加したくない場合は、独自の関数を作成して、本当にやりたいことを実行できます。これには、非標準の関数であるという欠点があります。頻繁に使用する方が便利ですが、他の人を混乱させる可能性があります。


10

ベースを指定:

var number = parseInt(s, 10);

うわー、あなたたちは速いです。答えはクリップボードにもありました。ネオスタイルのインターネットに直接つながっていますか?
ポートマン、

1
悪魔がデフォルトで10をベースにしない理由
トム・グレン

2
多分それは主にString-> Number変換関数として意図されたのではなく、base b number StringからNumberを読み取る関数のためです。
artistoex 2010年

2
デフォルトは10を底としていますが、先行ゼロは8進数を示すための広範な方法です。
ネイサン

7

2番目のパラメーターがない場合、parseIntを10進数を想定するバージョンに置き換えるのは非常にいたずらでしょうか?(注-テストされていません)

parseIntImpl = parseInt
parseInt = function(str, base){return parseIntImpl(str, base ? base : 10)}

2
はい、それはいたずらです-標準の動作に依存する他のコードを壊します。
jes5199 2009年

4
それは事実ですが、それほど多くはありません。また、これは標準の動作ではありません。8進サポートはオプションです。
Andrew Duffy、

2
しかし、オプションではない16進サポートも削除しますね。これは常に正しいはずですparseInt("0xFFFFFF") === 16777215が、エッチなハックを配置すると機能しなくなりますparseInt("0xFFFFFF") === 0
Timo


6

また、parseFloatまたはparseIntを使用する代わりに、単項演算子(+)を使用することもできます。

+"01"
// => 1

+"02"
// => 2

+"03"
// => 3

+"04"
// => 4

+"05"
// => 5

+"06"
// => 6

+"07"
// => 7

+"08"
// => 8

+"09"
// => 9

そして、十分に

+"09.09"
// => 9.09

MDNリンク

単項プラス演算子は、そのオペランドの前にあり、そのオペランドに評価されますが、それが数値でない場合は数値に変換しようとします。単項否定(-)も非数値を変換できますが、単項プラスは、数値に対して他の演算を実行しないため、何かを数値に変換する最も速く好ましい方法です


5

10進数の場合はどうでしょうか。

('09'-0) === 9  // true

('009'-0) === 9 // true

4

parseIntを使用してすでに一連のコーディングを行っており、すべてに「、10」を追加したくない場合は、関数をオーバーライドして、base 10をデフォルトにすることができます。

window._oldParseInt = window.parseInt;
window.parseInt = function(str, rad) {
    if (! rad) {
        return _oldParseInt(str, 10);
    }
    return _oldParseInt(str, rad);
};

これは後のリーダーを混乱させる可能性があるため、parseInt10()関数を作成する方がわかりやすいかもしれません。個人的には、常に "、10"を追加する必要があるよりも単純な関数を使用する方が好きです-間違いの機会が増えるだけです。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.