代码之家  ›  专栏  ›  技术社区  ›  Kris Selbekk

为什么我可以对日期对象进行数学运算?[副本]

  •  3
  • Kris Selbekk  · 技术社区  · 6 年前

    这个问题已经有了答案:

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

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

    为什么日期对象最终被强制转换为毫秒,然后减去毫秒?我知道他们会这样做,但我不知道导致这种情况的实际事件顺序是什么。

    4 回复  |  直到 6 年前
        1
  •  4
  •   baao    6 年前

    Javascript就是这样做的 automatic type conversion -就像算术运算(你在这里执行的)。你很幸运你减去了,如果你加上了它们,你最终会得到一个字符串,其中包含两个日期字符串,因为 toPrimitive (隐式调用)适用于日期。考虑以下内容

    // automatic casting
    console.log("1" - "1"); // 0
    // but
    console.log("1" + "1"); // 11
    
    // now with dates
    // automatic casting
    console.log(new Date() - new Date()); 0
    console.log(new Date() + new Date()); // Mon Jun 11 2018 10:10:36 GMT+0200 (Mitteleuropäische Sommerzeit)Mon Jun 11 2018 10:10:36 GMT+0200 (Mitteleuropäische Sommerzeit)

    上的规范 additional operator 有以下提示可以进一步解释这一点

    所有本机ecmascript对象,除了 日期对象 处理缺少提示的情况,就像给出了提示号一样;日期对象处理缺少提示的情况。 好像提示字符串 被给予。

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

    Date.prototype [ @@toPrimitive ] ( hint )
    

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

    也就是说。代码工作方式的原因是 subtraction ,提示 最主要的 返回一个数字。

        2
  •  5
  •   Steve    6 年前

    javascript对象可以定义一个方法 valueOf ,用于 Date 对象,将时间转换为epoch毫秒。然后,Javascript将在将对象转换为原语时自动使用此函数,仅在 一些 案例。

    令人困惑的是,javascript对象还可以定义一个方法 toString 将对象转换为字符串 日期 提供自定义实现)。作为 @baao mentions in his answer 在对对象执行“算术”时,由于类型的自动转换,这可能会导致一些问题。

    javascript是否选择使用 ToString公司 虚拟 价值 取决于上下文。有关详细信息,请参阅 this question ,请 the overall spec for addition (和 subtraction )和 the specific spec for Dates ( mdn link )和 @baao's answer 更深入的了解。但总的来说, 日期 (与大多数其他对象不同)默认为字符串转换,但由于减法需要两个数字才能有意义,因此它将日期转换为数字。

    在本例中,使用 价值 ,请 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/Date/valueOf

        3
  •  2
  •   Terry Wei    6 年前

    它等于 endTime.getTime() - startTime.getTime()

    如你所说,它们投射到毫秒,这正好显示了差异。

        4
  •  1
  •   ZER0    6 年前

    发生这种情况是因为JS在执行此类操作时通过方法请求日期对象的基元 valueOf .日期的对象 overrides valueOf 方法,使使用的值基本上与 getTime .

    您也可以自己尝试:

    const o = { valueOf: () => 10 };
    
    console.log(o + 1) // 11