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

发布于 2024-09-02 14:07:29 字数 758 浏览 8 评论 0 原文

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

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

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

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

为什么 null 像 0,尽管它实际上不是 0?

I had to write a routine that increments the value of a variable by 1 if its type is number and assigns 0 to the variable if not, where the variable is initially null or undefined.

The first implementation was v >= 0 ? v += 1 : v = 0 because I thought anything not a number would make an arithmetic expression false, but it was wrong since null >= 0 is evaluated to true. Then I learned null behaves like 0 and the following expressions are all evaluated to true.

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

Of course, null is not 0. null == 0 is evaluated to false. This makes the seemingly tautological expression (v >= 0 && v <= 0) === (v == 0) false.

Why is null like 0, although it is not actually 0?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

初心未许 2024-09-09 14:07:30

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

null >= 0; 为 true

(null==0)||(null>0) 为 false

null <= 0; 为 true,但 (null==0)||( null<0) 为 false

"" >= 0 也为 true

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

typeof null returns "object"

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

  1. 如果 < code>PreferredType 未传递,让 hint 为“默认”。
  2. 否则,如果 PreferredTypehint 字符串,则让 hint 为“string”。
  3. 否则 PreferredTypehint Number,让 hint 为“number”。
  4. exoticToPrimGetMethod(input, @@toPrimitive)
  5. ReturnIfAbrupt(exoticToPrim)
  6. 如果 exoticToPrim 不是未定义的,则
    a) 令结果为Call(exoticToPrim, input, «hint»)
    b) ReturnIfAbrupt(结果).
    c) 如果Type(result)不是Object,则返回结果。
    d) 抛出 TypeError 异常。
  7. 如果 hint 为“default”,则让 hint 为“number”。
  8. 返回OrdinaryToPrimitive(输入,提示)。

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

所以我认为 null 会转换为 0。

JavaScript has both strict and type–converting comparisons

null >= 0; is true
but
(null==0)||(null>0) is false

null <= 0; is true but (null==0)||(null<0) is false

"" >= 0 is also true

For relational abstract comparisons (<= , >=), the operands are first converted to primitives, then to the same type, before comparison.

typeof null returns "object"

When type is object javascript tries to stringify the object (i.e null)
the following steps are taken (ECMAScript 2015):

  1. If PreferredType was not passed, let hint be "default".
  2. Else if PreferredType is hint String, let hint be "string".
  3. Else PreferredType is hint Number, let hint be "number".
  4. Let exoticToPrim be GetMethod(input, @@toPrimitive).
  5. ReturnIfAbrupt(exoticToPrim).
  6. If exoticToPrim is not undefined, then
    a) Let result be Call(exoticToPrim, input, «hint»).
    b) ReturnIfAbrupt(result).
    c) If Type(result) is not Object, return result.
    d) Throw a TypeError exception.
  7. If hint is "default", let hint be "number".
  8. Return OrdinaryToPrimitive(input,hint).

The allowed values for hint are "default", "number", and "string". Date objects, are unique among built-in ECMAScript object in that they treat "default" as being equivalent to "string".
All other built-in ECMAScript objects treat "default" as being equivalent to "number". (ECMAScript 20.3.4.45)

So I think null converts to 0.

被翻牌 2024-09-09 14:07:30

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

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 !

I had the same problem !!.
Currently my only solution is to separate.

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 !
画▽骨i 2024-09-09 14:07:30

看起来检查 x >= 0 的方法是 !(x < 0) 这样响应才有意义。

It looks like the way to check x >= 0 is !(x < 0) In that way make sense the response.

明明#如月 2024-09-09 14:07:29

您真正的问题似乎是:

为什么:

null >= 0; // true

但是:

null == 0; // false

真正发生的是大于或等于运算符>=)执行类型强制转换(< a href="http://www.ecma-international.org/ecma-262/5.1/#sec-9.1" rel="nofollow noreferrer">ToPrimitive),带有hint类型的Number,实际上所有关系运算符都有这种行为。

null等于运算符 (==) 以特殊方式处理。简而言之,它仅强制未定义

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

false'0'[ ] 受到数字强制为零。当修剪空白后结果为空字符串 ("") 时,字符串强制为零。

您可以在 摘要中查看此过程的内部细节相等比较算法抽象关系比较算法

总结:

  • 关系比较:当调用 ToPrimitive(null,hint:Number) 且两个值都不是 String 类型时,将在两者上调用 ToNumber。这与在前面添加 + 相同,对于 null 强制转换为 0

这也解释了如何对 Date 对象进行数值比较。

对于 null >= 0,如 ToPrimitive(null,hint: Number) 结果 null

Null 结果等于输入参数(不转换)。

对于 EcmaScript 5.1 的“抽象关系比较算法”,这发生在步骤 3。EcmaScript

2025, 7.2.12 IsLessThan ( x, y, LeftFirst ),步骤 4 效果相同。 (请参阅:https://tc39.es/ecma262/#sec-islessthan

c.注意:因为 px 和 py 是原始值,所以求值顺序为
不重要。 d.让 nx 为 ?到数字(px)。 e.让尼吧?
ToNumeric(py)。

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

7.1.4 ToNumber(参数)
抽象操作 ToNumber 采用参数参数(ECMAScript 语言值)并返回包含 Number 的正常完成或抛出完成。它将参数转换为 Number 类型的值。调用时它执行以下步骤:
[[ ToPrimitive]],EcmaScript 5.1

  1. 如果参数是数字,则返回参数。
  2. 如果参数是 Symbol 或 BigInt,则抛出 TypeError 异常。
  3. 如果参数未定义,则返回 NaN。
  4. 如果参数为 null 或 false,则返回 +0

Your real question seem to be:

Why:

null >= 0; // true

But:

null == 0; // false

What really happens is that the Greater-than-or-equal Operator (>=), performs type coercion (ToPrimitive), with a hint type of Number, actually all the relational operators have this behavior.

null is treated in a special way by the Equals Operator (==). In a brief, it only coerces to undefined:

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

Values false, '0', and [] are subject to numeric coercion to zero. Strings coerce to zero when, after trimming whitespace, the result is the empty string ("").

You can see the inner details of this process in the The Abstract Equality Comparison Algorithm and The Abstract Relational Comparison Algorithm.

In Summary:

  • Relational Comparison: When ToPrimitive(null, hint: Number) is called, and both values are not type String, ToNumber is called on both. This is the same as adding a + in front, which for null coerces to 0.

This also explains how Date objects can be compared numerically.

As for null >= 0, as ToPrimitive(null, hint: Number) results null.

Null The result equals the input argument (no conversion).

For the "The Abstract Relational Comparison Algorithm" of EcmaScript 5.1, this occurs in step 3.

EcmaScript 2025, 7.2.12 IsLessThan ( x, y, LeftFirst ), step 4 the same effect. (see: https://tc39.es/ecma262/#sec-islessthan)

c. NOTE: Because px and py are primitive values, evaluation order is
not important. d. Let nx be ? ToNumeric(px). e. Let ny be ?
ToNumeric(py).

  • Equality Comparison: only calls ToNumber on Strings, Numbers, and Booleans.

7.1.4 ToNumber ( argument )
The abstract operation ToNumber takes argument argument (an ECMAScript language value) and returns either a normal completion containing a Number or a throw completion. It converts argument to a value of type Number. It performs the following steps when called:
[[ToPrimitive]], EcmaScript 5.1

  1. If argument is a Number, return argument.
  2. If argument is either a Symbol or a BigInt, throw a TypeError exception.
  3. If argument is undefined, return NaN.
  4. If argument is either null or false, return +0????.
  5. If argument is true, return 1????.
  6. If argument is a String, return StringToNumber(argument).
  7. Assert: argument is an Object.
  8. Let primValue be ? ToPrimitive(argument, NUMBER).
  9. Assert: primValue is not an Object.
  10. Return ? ToNumber(primValue).
记忆里有你的影子 2024-09-09 14:07:29

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

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

这毫无意义。就像人类语言一样,这些东西需要死记硬背。

I'd like to extend the question to further improve visibility of the problem:

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

It just makes no sense. Like human languages, these things need be learned by heart.

若水般的淡然安静女子 2024-09-09 14:07:29
console.log( null > 0 );  // (1) false
console.log( null == 0 ); // (2) false
console.log( null >= 0 ); // (3) true

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

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

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

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

Mathematically, that’s strange. The last result states that "null is greater than or equal to zero", so in one of the comparisons above it must be true, but they are both false.

The reason is that an equality check == and comparisons > < >= <= work differently. Comparisons convert null to a number, treating it as 0. That’s why (3) null >= 0 is true and (1) null > 0 is false.

On the other hand, the equality check == for undefined and null is defined such that, without any conversions, they equal each other and don’t equal anything else. That’s why (2) null == 0 is false.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文