我有点晚回答这个问题,但我认为我能给出一个好的答案。
被接受的答案并没有告诉你比你在问题中已经知道的更多,它提到:
Number(value)
作为
+value
工作,但不作为
parseInt(value)
。
关键是要知道在类型转换和解析之间存在语义差异。
因为
Number构造函数作为函数调用(
Number(value)
)和
一元操作符 +
(
+value
)在幕后使用
ToNumber内部操作。这些结构的目的是进行类型转换。
当
将ToNumber
应用于字符串类型时,使用特殊的语法产生,称为
StringNumericLiteral
。
此产生仅可容纳十进制文字和十六进制整数文字:
StrNumericLiteral :::
StrDecimalLiteral
HexIntegerLiteral
这个语法与“普通”NumericLiterals
的语法之间也存在语义差异。
StringNumericLiteral
:
- 可以在前面和/或后面带有空格和/或行终止符。
- 十进制数可以有任意数量的前导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
正如您所看到的,这引入了ES3和ES5实现之间行为上的不兼容性,因此建议始终使用基数参数以避免任何可能的问题。
现在是您的第二个问题:
为什么ECMAScript第五版在严格模式下删除了八进制字面量?
实际上,这个去除八进制字面量的努力可以追溯到1999年。自ECMAScript第三版规范以来,八进制字面量产生(OctalIntegerLiteral
和OctalEscapeSequence
)已从NumericLiteral
的语法中删除,它们可能会因向后兼容(也在ES5中)旧版本的标准而被包括在内。
事实上,它们包含在所有主要的实现中,但从技术上讲,一个符合ES3或ES5的实现可以选择不包括它们,因为它们被描述为非规范性的。
这是第一步,现在ECMAScript 5 严格模式完全禁止它们。
但是为什么?
因为八进制字面量被认为是一个容易出错的特性,实际上,在过去它们曾经引起了不经意或难以捕捉的错误,就像parseInt的隐式八进制问题一样。
现在,在严格模式下,八进制字面量将会导致SyntaxError异常——目前只能在Firefox 4.0 Beta中观察到。
StringNumericLiteral
,而且我肯定不知道允许使用空格。那只是其中一件事情,我总是期望空格会导致NaN。 - Andy EisNaN("\t\r\n ")
返回false
感到惊讶 ;) - Christian C. Salvadó