代码之家  ›  专栏  ›  技术社区  ›  Andy E

为什么不把八进制文字转换成字符串?

  •  23
  • Andy E  · 技术社区  · 14 年前

    在javascript中,为什么八进制数字字符串转换为十进制数字?我可以使用 Number() + 为什么不是八进制?

    例如:

    1000 === +"1000" // -> true
    0xFF === +"0xFF" // -> true
    0100 === +"0100" // -> false - +"0100" gives 100, not 64
    

    我知道我可以分析 parseInt("0100" [, 8]) 但是我想知道为什么施法不能像十六进制和十二进制那样工作。

    还有,有人知道为什么八进制文字会从ECMAScript第五版严格模式中删除吗?

    3 回复  |  直到 14 年前
        1
  •  24
  •   Marcel Korpel    14 年前

    这个问题我有点晚了,但我想我可以给出一个好的答案。

    接受的答案不会告诉你更多你实际知道的事情,并且在问题本身中提到: Number(value) 作品作为 +value 但不是 parseInt(value) .

    关键是要知道 语义差异 之间 类型转换 正在分析 .

    为什么八进制数字串转换为十进制数字?

    因为 Number constructor called as a Function ( 数量(值) )以及 Unary + Operator ( +值 )在幕后使用 ToNumber 内部操作。这些构造的目的是 类型转换 .

    什么时候? ToNumber is applied to the String Type 使用了一种特殊的语法产物,称为 StringNumericLiteral .

    此产品只能保存十进制文本和十六进制整数文本:

    ...
    
    StrNumericLiteral :::
       StrDecimalLiteral
       HexIntegerLiteral
    
    ...

    这种语法和“正常”语法也有语义上的区别。 NumericLiterals .

    字符串数字文本 :

    • 前面和/或后面可以是空格和/或行终止符。
    • 十进制可以有任何前导0位数。 没有八进制!
    • 小数点前面可以加上+或来表示其符号。
    • 空的或只包含空白的将被转换为+0。

    现在我要和 parseInt parseFloat 功能。

    这些功能的目的显然是 句法分析 ,这就是 语义上 不同于 类型转换 例如:

    parseInt("20px");     // 20
    parseInt("10100", 2); // 20
    parseFloat("3.5GB");  // 3.5
    // etc..
    

    值得一提的是 parseInt 在ECMAScript第5版规范中进行了更改,它不再将数字的基数解释为八进制,因为它具有前导零:

    parseInt("010"); // 10, ECMAScript 5 behavior
    parseInt("010"); // 8,  ECMAScript 3 behavior
    

    如你所见,这引入了 incompatibility 在ES3和ES5实现之间的行为中,建议始终使用基数参数,以避免任何可能的问题。

    现在你的第二个问题是:

    为什么八进制文字是从严格模式的ECMAScript第五版中删除的?

    实际上,这种去除八进制文字的努力是从1999年开始的。八进制文字生成( OctalIntegerLiteral OctalEscapeSequence )从语法中删除 NumericLiteral S自 ECMAScript 3rd Edition specification ,他们 可以 包括在内 backwards compatibility ( also in ES5 )标准的旧版本。

    实际上,它们包含在所有主要实现中,但从技术上讲,符合ES3或ES5的实现可以选择不包含它们,因为它们被描述为 非规范性 .

    这是第一步,现在是ECMAScript 5 Strict Mode 完全不允许。

    但是为什么呢?

    因为他们被认为是 易出错的 特征,事实上,在过去 无意的 难以捕捉 bugs_ 帕林特 艾斯。

    现在,在严格模式下,八进制文字将导致 SyntaxError 例外情况“目前仅在Firefox 4.0 Betas中可见”。

        2
  •  4
  •   Peter Bailey    14 年前

    因为你实际上没有在正确的意义上执行强制类型转换(JS没有强制类型转换),这只是类型转换。

    当您在javascript中有任何文字并在其上实现一个方法时,会在后台为您创建一个对象。

    "foo".toUpperCase() 例如,被大致如下所示的代码评估所取代 new String( "foo" ).toUpperCase();

    因为字符串不能用一元计算 + 运算符JS将字符串转换为数字,但它不使用 parseInt() parseFloat() 内部——你猜对了——它使用 Number() .

    所以,你看到的值就是你从 Number() ,似乎不假定为八进制。

        3
  •  2
  •   Jeff Walden    14 年前

    为了解释为什么ES5中取消了八进制支持,主要是因为对于新手或非程序员来说,语法是意外的。想象一下,垂直对齐一系列数字(可能是加起来的),使用前导零来对齐它们,例如——如果您的数字不使用8或9,它们最终将被视为八进制。突然,你的代码在杂草丛中消失了,没有明显的原因!这就是拆除八进制支架的原因。如果不造成这样的不幸,也许有一天会添加一个不同的八进制语法(我想我记得看到过 0o755 但现在八进制已经过时了。

    关于不相容 parseInt 在过去的答复中指出的变化:没有实现会做出这种改变,我怀疑没有实现会做出这种改变。ES5主要基于现实。它的新特性通常不会破坏现有的代码(当然,新的代码在使用新特性时必须注意不要破坏现有的代码作为使用的一部分),而不会尝试使用新特性。它的不兼容性也几乎可以忽略不计,或者它们是无关的,因为现实世界中的实现出于兼容性的原因而轻率地忽略了规范。但并非所有的不相容都是有根据的:有些是更渴望而不是协调。改变到 帕林特 是渴望改变的一个例子。它破坏了现有的代码,这些代码要求不带显式基数的八进制语法解析为八进制。

    几天来,spidermonkey(mozilla的javascript引擎)实现了一个中途的更改 帕林特 ,当从严格模式代码调用时,忽略八进制,并在不从严格模式代码调用时支持八进制。这更接近于ES5想要的,但是它是将非严格代码转换为严格模式的明显障碍,它可能会让用户感到困惑,而且——也许对实现者来说最有趣的是——这意味着您无法实现 帕林特 在JavaScript中(因为在规范中没有办法检查调用函数的严格性),这在将来可能是可取的(减少攻击面、简化实现等)。所以我们消除了依赖。(我写了补丁 帕林特 依赖于呼叫者,我查看了补丁以撤销它,这是在我的初始补丁登陆后进一步讨论产生的。) 帕森特 现在再次符合ES3,考虑到Web的现状,并且ES5的语义可能与它不兼容,我怀疑我们会改变。因此,我怀疑其他人也会改变。(我也很肯定他们会同意我们对网络不兼容程度的估计,以及ES5希望禁止在 帕森特 可能还有其他原因。即使我们要改变,我也不确定他们是否会跟随,我怀疑他们会聪明地不这样做。)