【问题标题】:How do I work around JavaScript's parseInt octal behavior?如何解决 JavaScript 的 parseInt 八进制行为?
【发布时间】:2010-10-25 10:05:47
【问题描述】:

尝试在 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

有什么解决方法?

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


更新:

第 5 版 JavaScript 标准 (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 年前)中,实现被“鼓励”不要这样做:“当基数是 0undefined 并且字符串的数字以 0 数字开头而不是 xX 时,则执行可以自行决定将数字解释为八进制或十进制。鼓励实现在这种情况下将数字解释为十进制。"(我的重点)

标签: javascript integer octal


【解决方案1】:

这是一个常见的 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
【解决方案2】:

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

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

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

是的,这非常骇人听闻,但非常方便......

【讨论】:

  • 当一个二进制或足够的情况下为什么要进行两个操作?
  • @Oleg,为什么一个就足够了?
  • @Grodriguez,当 |0 中的 0 是字符串?
  • 整个问题是关于 parseInt 的替代方法,用于将字符串转换为整数。因此:总是。
【解决方案3】:

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是很重要的,为了方便在函数表达式中使用,比如map in ["7","4","09","5"].map(parseInt); Map 会传递元素的index数组作为第二个参数,除非你包装它,否则 parseInt 将把它解释为基数。
【解决方案4】:
function parseDecimal(s) { return parseInt(s, 10); }

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

【讨论】:

    【解决方案5】:

    指定基数:

    var number = parseInt(s, 10);
    

    【讨论】:

    • 哇你们真快。我什至在剪贴板上都有我的答案。你是直接接入互联网的吗?新风格?
    • 为什么它不默认为base 10
    • 可能是因为它主要不是作为字符串->数字转换函数,而是从基数 b 字符串中读取数字的函数。
    • 默认以 10 为底,但前导零是表示八进制的普遍方式。
    【解决方案6】:

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

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

    【讨论】:

    • 是的,那会很淘气——它会破坏其他依赖于标准行为的代码。
    • 确实如此,但没有太多。这也不是标准行为 - 八进制支持是可选的。
    • 但是您还放弃了非可选的十六进制支持,是吗?这应该永远是正确的:parseInt("0xFFFFFF") === 16777215,但是你的顽皮黑客已经到位,它不再有效parseInt("0xFFFFFF") === 0
    【解决方案7】:

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

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

    【讨论】:

      【解决方案8】:

      十进制怎么样:

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

      【讨论】:

        【解决方案9】:

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

        【讨论】:

          【解决方案10】:

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

          【讨论】:

          • 是的,看起来有人终于决定八进制的东西造成的问题比解决的问题多。虽然不愿意成为实际使用/依赖该功能的 0.01% 的人之一,在该功能中,任何以 0 开头的东西都会被解析为八进制。 :)
          • 这会给某些人带来一些非常讨厌的错误!
          猜你喜欢
          • 1970-01-01
          • 2017-04-04
          • 1970-01-01
          • 2013-09-27
          • 2015-11-25
          • 1970-01-01
          • 2015-09-15
          • 2016-03-27
          • 2021-09-10
          相关资源
          最近更新 更多