为什么我可以使用Date对象进行数学运算?

Kri*_*ekk 3 javascript

当我减去两个Date对象时,如下所示:

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

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

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

Ste*_*eve 5

JavaScript对象可以定义一个方法valueOf,对于Date对象,将时间转换为纪元毫秒.只有在某些情况下,JavaScript才会在将Object转换为基元时自动使用此函数.

令人困惑的是,JavaScript对象还可以定义一个方法toString,该方法将对象转换为String(并Date提供自定义实现).正如@baao在他的回答中提到的,由于类型的自动转换,这可能在对对象进行"算术"时引起一些问题.

JavaScript选择使用toStringvs valueOf取决于上下文.有关更多信息,请参阅此问题,添加(和减法)的整体规范,以及日期(mdn链接)的具体规范,以及@ baao的答案以获得更深入的了解.但总的来说,Date(与大多数其他对象不同)默认为字符串转换,但由于减法需要两个数字才有意义,因此它将日期转换为数字.

显式定义行为通常是个好主意,在这种情况下使用valueOf,getTime或者toString使代码不那么模糊.

也可以看看:

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 /日期/的valueOf


chr*_*con 5

这就是 javascript 如何进行自动类型转换- 就像算术运算(您在此处执行的)一样。你很幸运,你减去了它们,如果你添加了它们,你最终会得到一个连续包含两个日期字符串的字符串,因为toPrimitive(隐式调用)对于日期的工作方式。考虑以下

\n\n

\r\n
\r\n
// automatic casting\r\nconsole.log("1" - "1"); // 0\r\n// but\r\nconsole.log("1" + "1"); // 11\r\n\r\n// now with dates\r\n// automatic casting\r\nconsole.log(new Date() - new Date()); 0\r\nconsole.log(new Date() + new Date()); // Mon Jun 11 2018 10:10:36 GMT+0200 (Mitteleurop\xc3\xa4ische Sommerzeit)Mon Jun 11 2018 10:10:36 GMT+0200 (Mitteleurop\xc3\xa4ische Sommerzeit)
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n\n

关于附加运算符的规范有以下提示,进一步解释了这一点

\n\n
\n

除了Date 对象之外,所有本机 ECMAScript 对象都会处理提示缺失的情况,就好像给出了提示 Number 一样;日期对象处理缺少提示的情况,就像给出提示字符串一样。

\n
\n\n

使用算术运算符时,JavaScript 会将您的值转换为基元,此处调用的方法是

\n\n
Date.prototype [ @@toPrimitive ] ( hint )\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

Date.prototype [ @@toPrimitive ] ( 提示 ) \n 此函数由 ECMAScript 语言运算符调用,以将 Date 对象转换为原始值。提示的允许值为“默认”、“数字”和“字符串”。日期对象在内置 ECMAScript 对象中是唯一的,因为它们将“default”视为等同于“string”,所有其他内置 ECMAScript 对象将“default”视为等同于“number”。

\n
\n\n

就是这样说的。您的代码之所以如此工作的原因是后来由减法toPrimitive执行的自动转换,它给出了返回数字的提示。

\n