只是出于好奇。
typeof NaN是number似乎不太符合逻辑。就像NaN === NaN或NaN == NaN返回false。这是JavaScript的特性之一吗,或者有什么原因吗?
编辑:谢谢你的回答。然而,让人明白这不是一件容易的事情。阅读答案和维基我明白了更多,但仍然,一句话像
与NaN的比较总是返回无序结果,即使是与NaN本身比较也是如此。比较谓词是信号或非信号,信号版本表示此类比较的无效异常。等式和不等式谓词是非信号,因此x = x返回false可用于测试x是否为静态NaN。
让我头晕目眩。如果有人能把它翻译成人类(而不是数学家)可读的语言,我会很感激。
好吧,这似乎有点奇怪,所谓的“不是一个数字”被认为是一个数字,但NaN仍然是一个数字类型,尽管事实如此:-)
NaN仅仅意味着特定的值不能在数字类型的限制范围内表示(尽管这可以说是所有必须四舍五入以适应的数字,但NaN是一个特殊情况)。
一个特定的NaN不等同于另一个NaN,因为它们可能是不同的值。然而,NaN仍然是一种数字类型,就像2718或31415一样。
至于你更新的问题,用外行的话解释一下:
与NaN的比较总是返回无序结果,即使是与NaN本身比较也是如此。比较谓词是信号或非信号,信号版本表示此类比较的无效异常。等式和不等式谓词是无信号的,因此x = x返回false可用于测试x是否为静态NaN。
所有这一切的意思是(分解为几个部分):
与NaN的比较总是返回无序结果,即使是与NaN本身比较也是如此。
基本上,一个NaN不等于任何其他数字,包括另一个NaN,甚至包括它自己。
比较谓词是信号或非信号,信号版本表示此类比较的无效异常。
试图在一个NaN和另一个数字之间进行比较(小于、大于等)操作,可能导致抛出异常(发出信号),也可能导致结果为false(非发出信号或为quiet)。
等式和不等式谓词是无信号的,因此x = x返回false可用于测试x是否为静态NaN。
相等(等于,不等于)的测试永远不会发出信号,因此使用它们不会导致异常。如果有一个正则数x,那么x == x总是成立的。如果x是一个NaN,那么x == x将永远是假的。它为您提供了一种轻松(悄悄)检测NaN的方法。
它的意思是不是一个数字。这不是javascript的特性,而是常见的计算机科学原理。
从http://en.wikipedia.org/wiki/NaN:
There are three kinds of operation
which return NaN:
Operations with a NaN as at least one operand
Indeterminate forms
The divisions 0/0, ∞/∞, ∞/−∞, −∞/∞, and −∞/−∞
The multiplications 0×∞ and 0×−∞
The power 1^∞
The additions ∞ + (−∞), (−∞) + ∞ and equivalent subtractions.
Real operations with complex results:
The square root of a negative number
The logarithm of a negative number
The tangent of an odd multiple of 90 degrees (or π/2 radians)
The inverse sine or cosine of a number which is less than −1 or
greater than +1.
所有这些值可能都不相同。NaN的一个简单测试是测试value == value为false。
typeof NaN返回'number',因为:
ECMAScript spec says the Number type includes NaN:
4.3.20 Number type
set of all possible Number values including the special “Not-a-Number”
(NaN) values, positive infinity, and negative infinity
So typeof returns accordingly:
11.4.3 The typeof Operator
The production UnaryExpression : typeof UnaryExpression is
evaluated as follows:
Let val be the result of evaluating UnaryExpression.
If Type(val) is Reference, then
If IsUnresolvableReference(val) is true, return "undefined".
Let val be GetValue(val).
Return a String determined by Type(val) according to Table 20.
Table 20 — typeof Operator Results
==================================================================
| Type of val | Result |
==================================================================
| Undefined | "undefined" |
|----------------------------------------------------------------|
| Null | "object" |
|----------------------------------------------------------------|
| Boolean | "boolean" |
|----------------------------------------------------------------|
| Number | "number" |
|----------------------------------------------------------------|
| String | "string" |
|----------------------------------------------------------------|
| Object (native and does | "object" |
| not implement [[Call]]) | |
|----------------------------------------------------------------|
| Object (native or host and | "function" |
| does implement [[Call]]) | |
|----------------------------------------------------------------|
| Object (host and does not | Implementation-defined except may |
| implement [[Call]]) | not be "undefined", "boolean", |
| | "number", or "string". |
------------------------------------------------------------------
此行为符合IEEE浮点运算标准(IEEE 754):
4.3.19 Number value
primitive value corresponding to a double-precision 64-bit binary
format IEEE 754 value
4.3.23 NaN
number value that is a IEEE 754 “Not-a-Number” value
8.5 The Number Type
The Number type has exactly 18437736874454810627 (that is, 253−264+3)
values, representing the double-precision 64-bit format IEEE 754
values as specified in the IEEE Standard for Binary Floating-Point
Arithmetic, except that the 9007199254740990 (that is, 253−2) distinct
“Not-a-Number” values of the IEEE Standard are represented in
ECMAScript as a single special NaN value. (Note that the NaN value
is produced by the program expression NaN.)
NaN的一个更好的名称应该是一个数值例外,它更准确地描述了它的含义,而且不那么容易混淆。它实际上是另一种伪装成具有原始类型的异常对象(通过语言设计),同时它在错误的自我比较中不被视为原始类型。这就是困惑。只要语言“不下定决心”在适当的例外对象和原始数之间进行选择,这种混乱就会存在。
The infamous non-equality of NaN to itself, both == and === is a manifestation of the confusing design forcing this exception object into being a primitive type. This breaks the fundamental principle that a primitive is uniquely determined by its value. If NaN is preferred to be seen as exception (of which there can be different kinds), then it should not be "sold" as primitive. And if it is wanted to be primitive, that principle must hold. As long as it is broken, as we have in JavaScript, and we can't really decide between the two, the confusion leading to unnecessary cognitive load for everyone involved will remain. Which, however, is really easy to fix by simply making the choice between the two:
要么使NaN成为一个特殊的异常对象,其中包含有关异常如何产生的有用信息,而不是将当前实现的信息丢弃,导致更难调试的代码;
或者让NaN成为一个基本类型为number的实体(称为“numeric”不那么容易混淆),在这种情况下,它应该等于自身,不能包含任何其他信息;后者显然是一个较差的选择。
将NaN强制转换为数字类型的唯一可以想象的好处是能够将其扔回任何数值表达式中。然而,这使得它成为脆弱的选择,因为任何包含NaN的数值表达式的结果都将是NaN,或者导致不可预测的结果,例如NaN < 0求值为false,即返回布尔值而不是保持异常。
即使“事情就是这样”,也没有什么能阻止我们为自己做出明确的区分,以帮助我们的代码更可预测,更容易调试。在实践中,这意味着识别这些异常并将其作为异常处理。不幸的是,这意味着更多的代码,但希望通过Flowtype的TypeScript等工具来缓解。
然后我们有混乱的安静和嘈杂,即信号NaN的区别。这实际上是关于如何处理异常,而不是异常本身,与其他异常没有什么不同。
类似地,Infinity和+Infinity是出现在实数线扩展中的数字类型元素,但它们不是实数。在数学上,它们可以用收敛到正无穷或负无穷的实数序列来表示。