我的问题有点晚了,但我想我可以给出一个很好的答案。
接受的答案并没有告诉你更多你实际知道的东西,并在问题本身中提到:Number(value)
作为+value
但不是作为parseInt(value)
.
关键是要知道类型转换和解析之间存在语义差异。
为什么八进制数字符串转换为十进制数?
因为在幕后调用为 Function ( Number(value)
) 的 Number 构造函数和一元+
运算符( ) 使用内部操作。这些构造的目的是类型转换。+value
ToNumber
当ToNumber
应用于字符串类型时,会使用一种特殊的语法产生式,称为StringNumericLiteral
.
这个产生式只能包含十进制文字和十六进制整数文字:
...
StrNumericLiteral :::
StrDecimalLiteral
HexIntegerLiteral
...
这种语法与“正常”的语法之间也存在语义差异NumericLiterals
。
答StringNumericLiteral
:
- 可以在空格和/或行终止符之前和/或之后。
- 也就是说,十进制可以有任意数量的前导 0 数字。没有八进制!
- 即十进制可以在前面加上 + 或 - 来表示它的符号。
- 即为空或仅包含空格将转换为 +0。
现在我将使用parseInt
andparseFloat
函数。
这些函数的目的显然是解析,这在语义上与类型转换不同,例如:
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
如您所见,这导致ES3 和 ES5 实现之间的行为不兼容,并且一如既往地建议使用 radix 参数,以避免任何可能的问题。
现在你的第二个问题:
为什么在严格模式下从 ECMAScript 第 5 版中删除八进制文字?
实际上,这种摆脱八进制文字的努力始于 1999 年。自ECMAScript 第 3 版规范OctalIntegerLiteral
以来,八进制文字产生式 (和OctalEscapeSequence
) 已从NumericLiteral
s的语法中删除,它们可能被包括在内以与旧版本向后兼容(也在 ES5 中)的标准。
事实上,它们包含在所有主要实现中,但从技术上讲,符合 ES3 或 ES5 的实现可以选择不包括它们,因为它们被描述为非规范性的。
那是第一步,现在 ECMAScript 5严格模式完全不允许它们。
但为什么?
因为它们被认为是一个容易出错的特性,事实上,在过去它们会导致无意或难以捕获的错误——就像隐式八进制的相同问题一样parseInt
。
现在,在严格模式下,八进制文字将导致SyntaxError
异常——目前只能在 Firefox 4.0 Beta 中观察到——。