Javascript 为什么我可以对日期对象进行数学运算?
当我减去两个日期对象时,如下所示:Javascript 为什么我可以对日期对象进行数学运算?,javascript,Javascript,当我减去两个日期对象时,如下所示: const startTime = new Date(); await someAsyncStuff(); const endTime = new Date(); const elapsedTime = endTime - startTime; console.log(`The async stuff took ${elapsedTime} ms`); 为什么日期对象最终被转换为毫秒,然后被减去?我知道他们是这样做的,但我无法找出导致这种情况的实际事件顺序
const startTime = new Date();
await someAsyncStuff();
const endTime = new Date();
const elapsedTime = endTime - startTime;
console.log(`The async stuff took ${elapsedTime} ms`);
为什么日期对象最终被转换为毫秒,然后被减去?我知道他们是这样做的,但我无法找出导致这种情况的实际事件顺序。它等于
endTime.getTime()-startTime.getTime()
正如您所说,它们转换为毫秒,这正好显示了差异。JavaScript对象可以定义一个方法
valueOf
,该方法用于Date
对象,将时间转换为历元毫秒。只有在某些情况下,JavaScript才会在将对象转换为原语时自动使用此函数
令人困惑的是,JavaScript对象还可以定义一个方法toString
,该方法将对象转换为字符串(并且Date
提供自定义实现)。例如,在对对象执行“算术”时,由于类型的自动转换,这可能会导致一些问题
JavaScript是否选择使用toString
vsvalueOf
取决于上下文。有关更多信息,请参阅,(和)和(),并进行更深入的了解。但总而言之,Date
(与大多数其他对象不同)默认为字符串转换,但由于减法需要两个数字才有意义,因此它将日期转换为数字
通常,明确定义行为是一个好主意,在这种情况下,使用valueOf
、getTime
或toString
来减少代码的歧义
另见:
之所以会发生这种情况,是因为JS在执行此类操作时通过方法请求日期对象的原语。日期的对象方法,因此使用的值与的基本相同 您也可以自己尝试:
const o = { valueOf: () => 10 };
console.log(o + 1) // 11
javascript就是这样做的——就像算术运算(您在这里执行的运算)。幸运的是,你减去了,如果你把它们加起来,你会得到一个字符串,一行包含两个日期字符串,因为toPrimitive
(隐式调用)是如何处理日期的。考虑下面的
//自动铸造
console.log(“1”-“1”);//0
//但是
console.log(“1”+“1”);//11
//现在是日期
//自动浇铸
console.log(new Date()-new Date());0
console.log(新日期()+新日期());//2018年6月11日星期一10:10:36 GMT+0200(Mitteleuropäische Sommerzeit)2018年6月11日星期一10:10:36 GMT+0200(Mitteleuropäische Sommerzeit)
但是JavaScript引擎如何知道对这些对象调用getTime()?这是一个硬编码的特殊情况吗?同样的方法你可以做15-“5”
,得到10因为日期对象是由他们创建的,他们这样做日期的减号运算符,我想真的应该是这样。哇,我不知道!还有一个很好的规范链接:我相信这就是发生的事情,是的@Steve我会接受这个作为“正确答案”,但这和@Steve的答案都在这里。谢谢你为我解释这一点做了大量的工作,我也相信@KrisSelbekk。谢谢你提出这个有趣的问题!因为javascript最初是在windows上实现的,如果它是linux的话,可能需要几微秒:)您可以使用.getTime()
,它将日期转换为毫秒,然后您可以执行-
操作。另外,await仅在异步函数中有效,因此您应该创建一个像(async()=>{await yourFunction()})这样的自调用函数
调用waitThreak@MihaiT-我的意思是上面的伪代码。我实际上是在寻找为什么我可以用实际的日期实例进行数学运算的答案(为什么我可以不调用getTime()
就减去它们)但是,当你使用+
操作数时,它的工作方式就不一样了——字符串连接被认为比算术更重要吗?你能告诉我规范中破坏这一点的部分吗?我不相信这个答案是正确的(但我真的不知道,我想学习)。如果是,将这两个日期相加将产生4036年的日期,但是对于重载的加号运算符,它不会在调用valueOf
之前调用toString
?是的。就像在《自动铸造》中解释的那样,我相信正确的答案应该是你我的结合。仍然在搜索thoughI发现这个答案特别有启发性:如果您感兴趣,可以链接到spec: