首页 > 解决方案 > 为什么我可以用 Date 对象做数学运算?

问题描述

当我像这样减去两个日期对象时:

const startTime = new Date();
await someAsyncStuff();
const endTime = new Date();

const elapsedTime = endTime - startTime;
console.log(`The async stuff took ${elapsedTime} ms`);

为什么 Date 对象最终被转换为毫秒,然后减去?我知道他们这样做,但我无法弄清楚导致这种情况的实际事件顺序是什么。

标签: javascript

解决方案


一般来说,JavaScript 对象可以定义方法来将对象转换为字符串或数字(您可以通过定义toStringvalueOf方法来自定义)。JavaScript 将在数值上下文(如2 * a)或字符串上下文(如'' + a)中使用这些方法将对象转换为适当的原语。

在不确定是使用数字还是字符串转换(如a + b)的上下文中,存在默认行为,具体取决于对象的类型。有趣Date的是,在默认的 ECMAScript 对象中被挑选出来以转换为字符串,而不是数字。通过规范

日期对象在 ECMAScript 内置对象中是唯一的,因为它们将“ default”视为等同于“ string”,所有其他内置 ECMAScript 对象将“ default”视为等同于“ number”。

Date对象的特定情况下,数值转换valueOf方法)将时间转换为纪元毫秒,而字符串转换toString方法)将对象转换为人类可读的字符串。正如@baao 在他的回答中提到的那样,由于类型的自动转换,这可能会在对对象进行“算术”时导致一些问题。

总之,Date(与大多数其他对象不同)默认为字符串转换,但由于减法需要两个数字才能有意义,因此它将日期转换为数字。

明确定义行为通常是一个好主意,在这种情况下使用valueOf,getTimetoString使代码不那么模棱两可。

有关 JavaScript 是否选择使用toStringvs的更多信息valueOf,请参阅此问题、加法(和减法的总体规范以及日期的具体规范mdn 链接),以及@baao 的答案以获得更深入的了解。

也可以看看:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/valueOf


推荐阅读