如何解决JavaScript的parseInt八进制行为?


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中没有"8""9",所以该函数返回零。是否喜欢,这是设计使然

有哪些解决方法?

注意:为了完整起见,我将发布一个解决方案,但这是我讨厌的解决方案,因此请发布其他/更好的答案。


更新:

JavaScript标准的第5版(ECMA-262)引入了一项重大更改,消除了此行为。Mozilla有一个很好的写了


21
第1步:帮自己一个忙,并始终包括前面的答案以及道格的书中提到的基数。第2步:如果您认真学习JavaScript,那么请给自己找一份道格的书。这是无价的。到目前为止我最喜欢的书。这是一份评论,仅供参考:realtech.burningbird.net/learning-javascript/basics/…–
fuentesjr

8
在与ECMAScript 5th Edition兼容的浏览器(例如Internet Explorer 9 10)中,除非要解析的数字以开头,否则基本参数默认为(十进制)0x,例如0xFF,在这种情况下,基本参数默认为16。将是遥远的记忆。
Andy E

2
怎么样+'08' === 8?真正!也许您确实需要parseInt真正的代码,但上面并不需要。
kojiro 2011年

1
a)这不是错误,请修复标题b)Number('08')
OnTheFly 2012年

4
@portman:“第5版...引入了消除这种行为的重大更改”可能值得指出的是,即使在第3版(13年前)中,也“鼓励”实现而不是这样做:“当基数等于0undefined并且字符串的数字以0不以x或开头的数字开头X,则实现可以自行决定将数字解释为八进制还是十进制。在这种情况下,建议实现将数字解释为十进制。(我的重点)
TJ Crowder 2012年

Answers:


328

这是一个简单的解决方案,是常见的Javascript陷阱:

只需指定base或“ radix”,如下所示:

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

您也可以使用Number

Number('08'); // 8

57
编号。辉煌。
波特曼

10
Number需要在08前后加上引号。同样要注意,Number('08 .123')将产生8.123作为其输出。如果您确实想要一个整数,请不要使用Number(或对您的输入进行模式匹配以仅确保整数)。
杰森S

3
数(08); 给我8在Firefox和IE中。
Paolo Bergantino,2009年

3
它不是ECMAscript标准的一部分。我正在使用Spidermonkey 1.7(= Firefox JS引擎)的JSDB上进行测试,并抱怨“ 08并非合法的ECMA-262八进制常量”
Jason S,2009年

5
不过,请在引号中使用“ 08”。08不符合ECMA-262标准,并且不能保证成功时不带警告和/或错误和/或特定的指定行为。
杰森S

43

如果您知道您的值将在有符号的32位整数范围内,那么~~x它将在所有情况下都可以正确执行。

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

如果您查找的不是二进制(~),则规范要求对参数进行“ ToInt32”转换,该转换将明显转换为Int32,并指定将NaN值强制为零。

是的,这确实令人难以置信,但是非常方便。


2
为什么一个二进制或两个就足够进行两次操作?
Oleg V. Volkov

@Oleg,为什么一个就够了?
塞巴斯蒂安

3
@SebastianGodelet,| 0。
Oleg V. Volkov

@Grodriguez,并且| 0中的0是字符串吗?
Oleg V. Volkov

整个问题是关于parseInt的替代方法,用于将字符串转换为整数。因此:总是。
Grodriguez 2014年

24

parseInt文档中,使用可选的radix参数指定以10为基数:

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

这让我感到腐,困惑和冗长(真的,每个parseInt中都有一个额外的论点吗?),所以我希望有更好的方法。


6
如果您不喜欢Verbosity,那么只需编写自己的函数即可调用内置函数并填写参数,而这些参数始终保持不变。
杰森S

3
权宜之计,因为并非像StackOverflow上的每个人都会为您编写函数parseIntB10所指责。为此,编写自己的包装函数是一个糟糕的主意。
Stefan Kendall,2009年

2
@iftrue:我想你错过了我的观点。我个人不介意只在各处执行parseInt(someString,10)来确保我强制以10为基数。需要。(这显然是JQuery背后的思想:通过增加额外的复杂性使其变得方便。我不使用JQuery,但许多人发现它很有用。)
Jason S,2009年

4
实际上,包装起来很重要,parseInt以便在函数表达式中方便使用,例如mapin ["7","4","09","5"].map(parseInt); Map会将数组中元素的索引作为第二个参数传递,parseInt除非将其包装,否则它将被解释为基数。
Plynx

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

编辑:如果您不希望一直将“,10”一直添加到parseInt()调用中,则可以选择使自己的函数执行您真正想要的操作。它具有非标准功能的缺点:如果您经常使用它,将会给您带来更多便利,但对于其他人则可能会造成混乱。


10

指定基数:

var number = parseInt(s, 10);

哇,你们很快。我什至在剪贴板上有我的答案。您是否直接插入Neo风格的Internet?
波特曼,

1
为什么魔鬼没有默认为10-
汤姆·古伦

2
可能是因为它并不是主要用于String-> Number转换函数,而是从基数b的String读取Number的函数。
artistoex

2
它默认为以10为底,但是前导零是指示八进制的一种广泛使用的方法。
内森2010年

7

如果没有第二个参数,将parseInt替换为假定十进制的版本会很顽皮吗?(注意-未测试)

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

2
是的,这很顽皮-它将破坏依赖于标准行为的其他代码。
jes5199

4
是的,但是没有太多。这也不是标准行为-八进制支持是可选的。
Andrew Duffy

2
但是,您也放弃了十六进制支持,这不是可选的,对吗?这应该永远是对的:parseInt("0xFFFFFF") === 16777215,但是您的顽皮破解就不再起作用了parseInt("0xFFFFFF") === 0
Timo 2013年


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

十进制如何呢:

('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”-只会增加出错的机会。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.