为什么 NaN = !NaN return 为真?

Why does NaN = !NaN return true?

NaN 是来源可疑的残留实现之一,但在大多数情况下我明白了。但是,我今天在 Node 提示符中输入了这个,但并不能真正理解它...

NaN = !NaN
> true

这只是返回!NaN的计算结果吗?这是有道理的,但令我惊讶的是,尝试将 NaN 分配给另一个值时没有出现错误。

注意:这道题是关于这个具体语法结构的;有很多与 NaN 和 isNaN 相关的问题,但谷歌搜索后我找不到答案。感谢 Ori Drori .

console.log(NaN = !NaN);

= 是赋值运算符。 ===== 是比较运算符。

NaN == !NaN
false
NaN === !NaN
false

也许更令人惊讶:

NaN  == NaN
false
NaN  === NaN
false

有关 NaN 的更多信息:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/NaN

您将 true 分配给 NaN,而不是使用 ===== 比较 NaN!NaN,因此操作 returns赋值->true。 Javascript 默默地忽略了这个赋值,因为 NaN is read only.

console.log(NaN = true);

// NaN hasn't changed
console.log(NaN);

如果您将 use strict 添加到代码中,JS 将抛出 read only 错误:

'use strict';
NaN = true;

使用 = 运算符,您可以将值分配给变量。但是,您不知道的是,通过这样做,它 returns 被分配的值。键入:

v = 1

在 JavaScript REPL 中将显示 1,因为这是分配给 v 的内容。所以,这样做:

NaN = !NaN

会将NaN的相反值赋给NaN本身。因为boolean中的NaNfalse,那么boolean中的!NaN一定是true.

Javascript真的很奇怪:当你写

NaN = true  // true

你基本上在你的陈述中做了,你得到 "true"。这与您编写

时的行为相同
a = true  // true

其中作业的右侧是 returned。但是如果你加上var然后写

var a = true  // undefined

那么 return 什么都没有。此外,如果您将 NaN 替换为计算结果为 NaN 的表达式,例如

1/"a" = true  // error!

然后你得到一个 ReferenceError。我建议永远不要使用赋值的 return 值。该行为是不确定的,您的代码将难以阅读。您可以启用 "strict mode" 来为您检查。

strict 模式下尝试 运行 Javascript 以避免大多数问题。

NaN、null、false、""、null、undefined、0 等它们在 javascript 中被视为虚假值(记住 falsy !== false),否无论您是否使用 strict 模式。

// 'use strict';

console.log(!NaN);       // true
console.log(!null);      // true
console.log(!false);     // true
console.log(!"");        // true
console.log(!null);      // true
console.log(!undefined); // true
console.log(!0);         // true

在 Python 中也是如此,除了 NaN。例如,

print(not False)        # True
print(not None)         # True
print(not float("NaN")) # False
print(not "")           # True
print(not 0)            # True

混淆的根源 当我们使用多种语言时,有时可能会造成混淆。

例如,

在 Python 'cat' in ['fat', 'cat', 'rat', 'hat'] returns 正确。

在Javascript 'cat' in ['fat', 'cat', 'rat', 'hat'](完全相同的一段代码)returns false 不管你是否使用strict模式。

在Pythonprint(not [])returns中

在Javascriptconsole.log(![]);returns错误。

这就是为什么我总是喜欢使用调试器、REPL 等的原因之一,无论代码多么简单。