【问题标题】:Why `null >= 0 && null <= 0` but not `null == 0`?为什么`null >= 0 && null <= 0`而不是`null == 0`?
【发布时间】:2010-05-26 06:19:32
【问题描述】:

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

第一个实现是v &gt;= 0 ? v += 1 : v = 0,因为我认为任何不是数字的东西都会使算术表达式为假,但这是错误的,因为null &gt;= 0 被评估为真。然后我了解到null 的行为类似于 0,并且以下表达式都被评估为 true。

  • null &gt;= 0 &amp;&amp; null &lt;= 0
  • !(null &lt; 0 || null &gt; 0)
  • null + 1 === 1
  • 1 / null === Infinity
  • Math.pow(42, null) === 1

当然,null 不是 0。null == 0 被评估为假。这使得看似重言式的表达(v &gt;= 0 &amp;&amp; v &lt;= 0) === (v == 0) 为假。

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

【问题讨论】:

  • 他在谈论 Javascript。您的示例在 PHP 中。在 PHP 中 operator== 以一种特殊的方式比较值。您可以进行一些非常疯狂的比较,例如“10”==“1e1”(这是真的)。如果你使用 operator===,你会得到一个完全不同的结果,因为它会检查类型是否匹配以及值是否匹配。查看此链接:php.net/manual/en/language.operators.comparison.php
  • PHP '==' 运算符确实以“特殊”方式工作。
  • 如果您的要求是从 1 而不是 0 开始计数,那么有一种非常简洁的方法可以增加最初为 nullundefined 的计数器:c = -~c // Results in 1 for null/undefined; increments if already a number
  • undefined 是一个变量值,用于未初始化的变量。另一方面,null 是一个空对象值,不应与数字混合。 null 不应与数字组合,因此 null 不应表现得像数字。
  • @AtesGoral - 简洁,但不明显。值得提醒人们,每当做一些不明显的事情时,请添加注释来解释代码的作用。在大多数情况下,我会认为这是一种“过早的优化”,因为它会用清晰度换取微小的性能提升。

标签: javascript null comparison equality


【解决方案1】:

你真正的问题似乎是:

为什么:

null >= 0; // true

但是:

null == 0; // false

真正发生的是 大于或等于运算符 (&gt;=),使用 hint 类型执行类型强制 (ToPrimitive) Number,其实所有的关系运算符都有这种行为。

null等于运算符 (==) 以特殊方式处理。简而言之,它只是强制undefined

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

false'''0'[] 等值受数字类型强制,它们都强制为零。

你可以在The Abstract Equality Comparison AlgorithmThe Abstract Relational Comparison Algorithm看到这个过程的内部细节。

总结:

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

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

【讨论】:

  • 嗨 CMS,根据您的解释,null 原语为 0,因此 0>=0 返回 true,== 返回 false。但根据 ecma 算法,如果 Type(x) 是 Object 和 Type( y) 是字符串或数字,返回比较结果 ToPrimitive(x) == y.then 应该返回 true。请解释一下
  • 对我来说,答案没有提供答案 - null is treated in a special way by the Equals Operator (==). In a brief, it only coerces to undefined: - 什么?你能解释一下,为什么null &gt;= 0? :)
  • @bharathmuppa @andrey-deineko:CMS 的其余答案在这里:The Abstract Relational Comparison Algorithm 在第 3 点中解释。如果两个值都不是字符串类型,则在两者上都调用 ToNumber。这与在前面添加+ 相同,它将null 强制转换为0。 Equality 仅在字符串、数字和布尔值上调用 ToNumber。
  • 很好的描述,但我不喜欢它。在任何语言中 (x == 0 || x > 0) 都应该等价于 (x >= 0)。 javascript 是一种愚蠢的语言。
  • 这只是规范中的一个错误(因为在数学上它是错误的)并且没有什么可做的,因为数以百万计的网站依赖于空比较^^'
【解决方案2】:

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

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

这毫无意义。就像人类语言一样,这些东西需要背诵下来。

【讨论】:

  • 如上所述,除了一个例外,可以解释为 == 如何处理 null,否则在所有情况下,null 都会使用 Number(nulll) 转换为 0
【解决方案3】:

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

null &gt;= 0; 为真 但 (null==0)||(null&gt;0) 是假的

null &lt;= 0; 为真,但(null==0)||(null&lt;0) 为假

"" &gt;= 0 也是如此

对于关系抽象比较(=),操作数首先转换为基元,然后转换为相同类型,然后再进行比较。

typeof null returns "object"

当 type 是 object 时,javascript 会尝试对对象进行字符串化(即 null) 采取以下步骤(ECMAScript 2015):

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

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

所以我认为null 转换为 0。

【讨论】:

    【解决方案4】:
    console.log( null > 0 );  // (1) false
    console.log( null == 0 ); // (2) false
    console.log( null >= 0 ); // (3) true
    

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

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

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

    【讨论】:

      【解决方案5】:

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

      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 &amp;&amp; a&gt;=0) 可能更清楚。这阐明了不简单地单独执行&gt;= 的原因:“a 可能为 null(或未定义,这也是 '== null')”。
      【解决方案6】:

      检查x &gt;= 0 的方法似乎是!(x &lt; 0) 这样才能使响应有意义。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-14
        • 1970-01-01
        • 2021-06-16
        • 2011-02-05
        • 1970-01-01
        相关资源
        最近更新 更多