为什么 `null >= 0 && null <= 0` 而不是 `null == 0`?

IT技术 javascript null comparison equality
2021-02-05 12:10:50

我必须编写一个例程,如果它的类型是number则将变量的值增加 1,如果不是,则将 0 分配给变量,其中变量最初是nullundefined

第一个实现是v >= 0 ? v += 1 : v = 0因为我认为任何不是数字的东西都会使算术表达式为假,但它是错误的,因为它被null >= 0评估为真。然后我学到了null像 0 一样的行为,并且以下表达式都被评估为真。

  • null >= 0 && null <= 0
  • !(null < 0 || null > 0)
  • null + 1 === 1
  • 1 / null === Infinity
  • Math.pow(42, null) === 1

当然null不是0。null == 0被评估为false。这使得看似同义反复的表达是(v >= 0 && v <= 0) === (v == 0)错误的。

为什么null像0,虽然它实际上不是0?

5个回答

你真正的问题似乎是:

为什么:

null >= 0; // true

但:

null == 0; // false

真正发生的是大于或等于运算符 ( >=),执行类型强制 ( ToPrimitive),带有提示类型Number,实际上所有关系运算符都有这种行为。

null等号运算符( ==)以特殊方式处理在简短的,它只强制转换undefined

null == null; // true
null == undefined; // true

值,例如false'''0',和[]被受数字类型强制,它们都强迫到零。

您可以在抽象平等比较算法抽象关系比较算法中看到这个过程的内部细节

总之:

  • 关系比较:如果两个值都不是 String 类型,ToNumber则在两者上调用。这与+在前面添加 a 相同,它对于 null 强制为0

  • 相等比较:仅调用ToNumber字符串、数字和布尔值。

嗨 CMS,根据您的解释,null 原语为 0,因此 0>=0 返回 true 并且 == 返回 false。但是根据 ecma 算法如果 Type(x) 是 Object 并且 Type(y) 是 String 或 Number,返回比较结果 ToPrimitive(x) == y.then 在这它应该返回 true.请解释我
2021-03-15 12:10:50
很好的描述,但我不喜欢它。在任何语言中 (x == 0 || x > 0) 应该等价于 (x >= 0)。javascript 是一种愚蠢的语言。
2021-03-20 12:10:50
我的回答并没有提供答案- null is treated in a special way by the Equals Operator (==). In a brief, it only coerces to undefined:-什么?你能解释一下,为什么null >= 0:)
2021-03-26 12:10:50
@bharathmuppa @andrey-deineko:CMS 的其余答案在这里: 抽象关系比较算法 ,它在第 3 点中进行了解释。如果两个值都不是 String 类型,则对两者都调用 ToNumber。这与+在前面添加 a 相同,它对于 null 强制为0Equality 仅对字符串、数字和布尔值调用 ToNumber。
2021-03-27 12:10:50
这实际上只是规范中的一个错误(因为在数学上它是错误的)并且没有任何关系,因为数百万个网站依赖于空值比较^^'
2021-04-05 12:10:50

我想扩展问题以进一步提高问题的可见性:

null >= 0; //true
null <= 0; //true
null == 0; //false
null > 0;  //false
null < 0;  //false

这没有任何意义。就像人类语言一样,这些东西需要用心学习。

如上所述,它可以解释为 == 如何处理 null,否则在所有情况下 null 都通过使用 Number(nulll) 转换为 0
2021-03-29 12:10:50

JavaScript 有严格比较和类型转换比较

null >= 0;是真的但是 (null==0)||(null>0)是假的

null <= 0;是真的但是(null==0)||(null<0)是假的

"" >= 0 也是如此

对于关系抽象比较 (<= , >=),在比较之前,操作数首先转换为原语,然后转换为相同的类型。

typeof null returns "object"

当类型为对象时,javascript 尝试对对象进行字符串化(即 null),执行以下步骤(ECMAScript 2015):

  1. 如果PreferredType未通过,则hint设为“默认”。
  2. 否则,如果PreferredTypehint字符串,则hint设为“字符串”。
  3. 否则PreferredTypehint数字,让我们hint成为“数字”。
  4. 我们exoticToPrimGetMethod(input, @@toPrimitive)
  5. ReturnIfAbrupt(exoticToPrim).
  6. 如果exoticToPrim不是未定义,则
    a) 令结果为Call(exoticToPrim, input, «hint»)
    乙)ReturnIfAbrupt(result)
    c) 如果Type(result)不是 Object,则返回结果。
    d) 抛出 TypeError 异常。
  7. 如果hint是“默认”,则hint设为“数字”。
  8. 返回OrdinaryToPrimitive(input,hint)

提示的允许值为“default”、“number”和“string”。日期对象在内置的 ECMAScript 对象中是独一无二的,因为它们将“默认”视为等同于“字符串”。 所有其他内置 ECMAScript 对象将 "default" 视为等同于 "number"( ECMAScript 20.3.4.45 )

所以我认为null转换为0。

console.log( null > 0 );  // (1) false
console.log( null == 0 ); // (2) false
console.log( null >= 0 ); // (3) true

在数学上,这很奇怪。最后一个结果表明“null 大于或等于零”,因此在上面的比较之一中它必须为真,但它们都为假。

原因是相等检查==和比较的> < >= <=工作方式不同。比较将 null 转换为数字,将其视为0. 这就是为什么 (3)null >= 0true和 (1)null > 0false

另一方面,==undefined的相等性检查null被定义为,在没有任何转换的情况下,它们彼此相等并且不等于其他任何东西。这就是为什么 (2)null == 0false

我有同样的问题 !!。目前我唯一的解决办法是分开。

var a = null;
var b = undefined;

if (a===0||a>0){ } //return false  !work!
if (b===0||b>0){ } //return false  !work!

//but 
if (a>=0){ } //return true !
,而不是做这可能是更清晰的:if (a!=null && a>=0)这阐明了不简单地自己做的原因>=:“a 可能为 null(或未定义,这也是 '== null')”。
2021-03-19 12:10:50