ChatGPT解决这个技术问题 Extra ChatGPT

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

尝试在 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 认为前导零表示 octal integer 的艰难方法,并且由于在 base-8 中没有 "8""9",因此该函数返回零。不管你喜不喜欢,this is by design

有哪些解决方法?

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

更新:

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

步骤 1)帮自己一个忙,并始终包括前面的答案以及 Doug 的书中提到的基数。第 2 步)如果你对学习 JavaScript 很认真,那就给自己买一本 Doug 的书。这是无价的。到目前为止我最喜欢的书。这是一条评论仅供参考:realtech.burningbird.net/learning-javascript/basics/…
在与 ECMAScript 第 5 版兼容的浏览器(例如 Internet Explorer 9)中,基本参数默认为 10(十进制),除非要解析的数字以 0x 为前缀,例如 0xFF,在这种情况下基本参数默认为16. 希望有一天,这个问题将成为遥远的记忆。
只是+'08' === 8怎么样?真的!也许您的真实代码确实需要 parseInt,但上述代码不需要。
a) 这不是错误,修复标题 b) Number('08')
@portman:“第 5 版...引入了消除这种行为的重大更改” 可能值得指出的是,即使在第 3 版(13 年前)中,实施也被“鼓励”不要这样做it: "当基数是 0undefined 并且字符串的数字以 0 数字开头而不后跟 xX 时,则实现可以自行决定解释数字可以是八进制或十进制。鼓励实现在这种情况下将数字解释为十进制。(我的重点)

g
groovecoder

这是一个常见的 Javascript 问题,有一个简单的解决方案:

只需 specify the base 或“基数”,如下所示:

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

您也可以使用 Number

Number('08'); // 8

Number 需要在 08 周围加上引号。另外请注意,Number('08.123') 将产生 8.123 作为其输出。如果您真的想要一个整数,请不要使用 Number (或模式匹配您的输入以确保仅整数)。
号码(08);在 Firefox 和 IE 中给我 8。
它不是 ECMAscript 标准的一部分。我正在使用 Spidermonkey 1.7(=Firefox JS 引擎)的 JSDB 上进行测试,并抱怨“08 不是合法的 ECMA-262 八进制常数”
不过,请在引号中使用“08”。 08 不符合 ECMA-262 标准,并且不能保证在没有警告和/或错误和/或特定指定行为的情况下成功。
老问题,但请注意 Number 与 parseInt 不同:stackoverflow.com/a/4090577
K
Karl Guertin

如果您知道您的值将在有符号的 32 位整数范围内,那么 ~~x 将在所有场景中执行正确的操作。

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

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

是的,这是令人难以置信的hackish,但非常方便......


当一个二进制或就足够时,为什么要进行两次操作?
@Oleg,为什么一个就足够了?
@Grodriguez,当 |0 中的 0 是字符串时?
整个问题是关于将字符串转换为整数的 parseInt 的替代方法。因此:总是。
P
Portman

parseInt documentation 中,使用可选的 radix 参数指定 base-10:

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

这让我觉得迂腐、混乱和冗长(真的,每个 parseInt 中都有一个额外的参数?)所以我希望有更好的方法。


如果您不喜欢冗长,那么只需创建自己的函数来调用内置函数并填写您始终保持不变的参数。
Riiiiiiight,因为它不像 StackOverflow 上的每个人都会责备你编写函数 parseIntB10。为此目的,编写自己的包装函数是一个糟糕的主意。
@iftrue:我认为你错过了我的观点。我个人不介意在任何地方都做 parseInt(someString, 10) 以确保我强制以 10 为基数。OP 似乎不喜欢这种方法,所以我建议了一个替代方案,我个人不会使用它,但也许它符合他的要求需要。 (这显然是 JQuery 背后的想法:通过增加额外的复杂性使其方便。我不使用 JQuery,但很多人觉得它很有用。)
实际上,包装 parseInt 以方便在函数表达式中使用非常重要,例如 ["7","4","09","5"].map(parseInt); 中的 map Map 会将数组中元素的 index 作为第二个参数传递,这除非您包装它,否则将被 parseInt 解释为基础。
J
Jason S
function parseDecimal(s) { return parseInt(s, 10); }

编辑:如果您不喜欢一直将“,10”添加到 parseInt() 调用中,则制作自己的函数来执行您真正想要的操作只是一种选择。它有一个非标准函数的缺点:如果你经常使用它对你来说更方便,但对其他人来说可能更混乱。


R
RichieHindle

指定基数:

var number = parseInt(s, 10);

哇你们真快。我什至在剪贴板上都有我的答案。您是否直接接入互联网,Neo 风格?
为什么魔鬼不是默认为 10
也许是因为它主要不是作为 String->Number 转换函数,而是从基数 b 数 String 中读取 Number 的函数。
它默认为以 10 为底,但前导零是表示八进制的一种普遍方式。
A
Andrew Duffy

如果 parseInt 没有第二个参数,那么用假定十进制的版本替换它会很淘气吗? (注意 - 未经测试)

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

是的,这很顽皮——它会破坏其他依赖于标准行为的代码。
这是真的,但没有太多。它也不是标准行为——八进制支持是可选的。
但是你也放弃了不是可选的十六进制支持,是吗?这应该永远是正确的:parseInt("0xFFFFFF") === 16777215,但你的顽皮黑客到位它不再起作用parseInt("0xFFFFFF") === 0
S
SoEzPz

您也可以使用一元运算符 (+),而不是使用 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 Link

一元加号运算符在其操作数之前并计算其操作数,但如果尚未将其转换为数字,则尝试将其转换为数字。虽然一元否定 (-) 也可以转换非数字,但一元加号是将某物转换为数字的最快和首选方法,因为它不对数字执行任何其他操作。


M
Mark Hall

十进制怎么样:

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

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

i
ingredient_15939

如果您已经使用 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”——这只会为错误创造更多机会。


A
Andrija

此问题无法在最新的 Chrome 或 Firefox (2019) 中复制。


是的,看起来有人最终决定八进制的东西造成的问题多于解决的问题。虽然不愿意成为实际使用/依赖该功能的 0.01% 的人之一,其中任何带有前导 0 的东西都会被解析为八进制。 :)
这将对某些人造成一些非常讨厌的错误!