为什么 (new Date() == new Date()) 是 false,但是 (Date() == Date()) 是 true?

5
我一直在使用JSFiddle解决FreeCodeCamp的“友好日期范围”问题。当我把Date作为字符串使用时(即不使用“new”):
案例1:
function isSameDay (dtFrom, dtTo) {
    return dtFrom == dtTo
  }

  let today = Date()
  let tomorrow = Date()

  console.log(today)
  console.log(tomorrow)
  console.log(isSameDay(today, tomorrow))

isSameDay返回true。然而,当我使用Date作为构造函数(带有“new”)时:

情况2:

function isSameDay (dtFrom, dtTo) {
    return dtFrom == dtTo
  }

  let today = new Date()
  let tomorrow = new Date()

  console.log(today)
  console.log(tomorrow)

  console.log(isSameDay(today, tomorrow))

isSameDay 返回 false。但是(!),当我添加一元运算符"+"时:
第三种情况:
function isSameDay (dtFrom, dtTo) {
    return dtFrom == dtTo
  }

  let today = + new Date()
  let tomorrow = + new Date()

  console.log(today)
  console.log(tomorrow)

  console.log(isSameDay(today, tomorrow))

isSameDay返回true。我理解情况1和情况3返回true,因为它们只是相同的字符串和相同的毫秒值。
为什么情况2返回false?

7
即使两个实例具有完全相同的属性,它们仍然是不同的对象,因此它们之间是不同的。如果想要比较日期,请将其转换为毫秒并比较该整数。同时,由于new Date()返回当前时间戳,因此两个new Date()调用之间可能会存在毫秒差异。 - Shilly
1
因为即使({}) == ({}),但是Date()返回一个字符串,所以大部分时间它们将会相等...除非秒数发生了变化。 - Jaromanda X
1
将它们转换为毫秒...但是偶尔会出现new Date().getTime() == new Date().getTime()是错误的情况...因为在两次调用new Date()之间可能会有一毫秒的时间差...使用Date() == Date()的可能性较小,因为它是一个具有1秒分辨率的字符串...但仍然可能偶尔出现错误。 - Jaromanda X
1
你可以通过准确度进行除法,或者根据所比较的是小时、分钟、秒或其他时间单位来进行减法和计数。将时间转换为毫秒主要是为了能够使用简单的数学运算,并不需要考虑本地化问题,与使用日期方法或生成的字符串相比更加方便。 - Shilly
谢谢您的回复,我不知道({}) != ({})。如果这是一个重复的问题,我很抱歉。 - AlexAlexson
2个回答

8
使用Date()方法,JavaScript的日期对象只能通过调用JavaScript Date作为构造函数来实例化:如果作为普通函数调用它(即不使用new运算符),将返回一个字符串而不是一个日期对象。MDN参考
typeof Date()    //"string"
Date() == Date() //true

使用构造函数new Date(),每个实例都是唯一的(相同构造函数的两个实例仍然彼此不同),这就是它们在比较时不相等的原因。

typeof new Date();        //"object"
new Date() === new Date() //false

每个实例都是独一无二的,但你不能用同样的论点来说 var a = 'a'; var b = 'a'; a == b; 应该评估为 false 吗?毕竟它们是不同的实例。另外,为什么所有其他比较如 <、> 等都可以使用日期对象,但 == 是一个不起作用的异常呢?看起来这是故意设计来混淆人的。 - tobuslieven
2
@tobuslieven 抱歉,但 var a = 'a'; var b = 'b'; a === b 的结果是 false。 - Radex
1
@tobuslieven,这是抽象相等比较算法的设计。请看下面我的回答。 - gotomanners

4
简单来说,Case 2返回false是因为您正在比较两个不同的对象引用(即使这两个对象包含完全相同的属性)。
而在其他情况下,您正在比较日期的toString()值。
请参阅 == 抽象相等算法的官方文档中的注释3。

NOTE 3

The equality operator is not always transitive. For example, there might be two distinct String objects, each representing the same String value.

Each String object would be considered equal to the String value by the == operator, but the two String objects would not be equal to each other. For Example:

new String("a") == "a" //true

"a" == new String("a") //true 

but

new String("a") == new String("a") //false.

为什么相等性只关心对象引用,而其他比较符号(如<、>等)似乎根据各自的日期正常工作? - tobuslieven
1
这是==运算符的一个特殊之处。与><等不同,相等性不是通过值而是通过引用来判断的。 - gotomanners
哇,这真有趣。不得不说这似乎是个糟糕的选择。有任何想法为什么他们决定要存在这个异常?我看不出有什么好处。 - tobuslieven
非常有趣。谢谢回复! - AlexAlexson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接