为什么八进制文字不能作为字符串转换为数字?

And*_*y E 23 javascript ecmascript-5

在JavaScript中,为什么八进制数字符串被转换为十进制数?我可以使用Number()或转换十六进制文字字符串+,为什么不使用八进制?

例如:

1000 === +"1000" // -> true
0xFF === +"0xFF" // -> true
0100 === +"0100" // -> false - +"0100" gives 100, not 64
Run Code Online (Sandbox Code Playgroud)

我知道我可以解析parseInt("0100" [, 8]),但我想知道为什么转换不像hex和dec数字那样工作.

另外,有没有人知道为什么在严格模式下从ECMAScript第5版中删除了八进制文字?

CMS*_*CMS 24

我对这个问题有点迟,但我想我能给出一个好的答案.

接受的答案并没有告诉你更多你真正知道的事情,并在问题本身中提到:Number(value)工作+value但不是parseInt(value).

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

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

因为作为Function(Number(value))调用Number构造函数和幕后的一元+运算符(+value)使用ToNumber内部操作.这些构造的目的是类型转换.

何时ToNumber应用于String Type,使用特殊的语法生成,称为StringNumericLiteral.

此生产只能包含十进制文字和十六进制整数文字:

...

StrNumericLiteral :::
   StrDecimalLiteral
   HexIntegerLiteral

...

这种语法与"正常"语法之间也存在语义差异NumericLiterals.

StringNumericLiteral:

  • 可以在空格和/或行终止符之前和/或之后.
  • 即十进制可以具有任意数量的前导0位.没有八角!
  • 即十进制可以在前面加+或 - 来表示其符号.
  • 那是空的或只包含空格被转换为+0.

现在我将使用parseIntparseFloat功能.

这些函数的目的显然是解析,它在语义上类型转换不同,例如:

parseInt("20px");     // 20
parseInt("10100", 2); // 20
parseFloat("3.5GB");  // 3.5
// etc..
Run Code Online (Sandbox Code Playgroud)

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

parseInt("010"); // 10, ECMAScript 5 behavior
parseInt("010"); // 8,  ECMAScript 3 behavior
Run Code Online (Sandbox Code Playgroud)

如您所见,这引入了ES3和ES5实现之间行为的不兼容性,并且建议始终使用radix参数,以避免任何可能的问题.

现在你的第二个问题:

为什么在严格模式下从ECMAScript第5版中删除了八进制文字?

实际上,自1999年以来,这种摆脱八进制文字的努力就出现了.自ECMAScript第3版规范以来,八进制文字作品(OctalIntegerLiteralOctalEscapeSequence)从NumericLiterals 语法中删除了,它们可能包含旧版本中以便向后兼容(也在ES5中)标准.

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

这是第一步,现在ECMAScript 5 严格模式完全不允许它们.

但为什么?

因为它们被认为是一个容易出错的特性,事实上,在过去它们引起了无意难以捕获的错误 - 正如同样的隐式八进制问题parseInt- .

现在,在严格模式下,八进制文字将导致SyntaxError异常 - 目前只能在Firefox 4.0 Betas中观察到 - .

  • 谢谢@Andy,是的,我经常看到人们感到惊讶,例如`isNaN("\ t\r \n")``返回`false`;) (2认同)