如果我运行这样一个简单的测试:
new Date(new Date(1050)).valueOf()
得到的不是1050,而是1000。这在Firefox和Internet Explorer中都会发生。
Google Chrome和Opera正确返回1000
内部日期很可能被转换为字符串,然后由外部日期的构造函数解析。
注意在所有浏览器中:
new Date(new Date(1050).toString()).valueOf()
返回1000,而:
new Date(new Date(1050).valueOf()).valueOf()
返回1050。
toString
的输出根本不包含任何毫秒级信息。
也许其他人可以回答为什么一些浏览器在这些"隐式转换"场景中使用toString
而不是valueOf
。我猜这个行为在ECMAScript规范中没有定义——但是我还没有检查过。
Matt有你的答案,但是要在规范中追踪它:
- §15.9.3.2规定
new Date(value)
首先调用ToPrimitive(value)
- topprimitive 可以用数字或字符串的提示来调用。如果没有提供提示,则默认为number ,但Date对象的除外,其中提示默认为string。所以 topprimitive 调用对象的toString方法,在本例中是Date.prototype。toString,它返回一个与实现相关的字符串,表示日期。
- 这个字符串然后由Date解析。parse,这也是非标准字符串的实现依赖,它将字符串转换为日期对象。
在toString或parse步骤期间,毫秒被丢弃。然而,我无法想象有什么理由将时间值转换为字符串,然后再转换回一个表达式中的时间值。
注意,这个解析意味着像new Date('5/5/70')
这样的东西将创建1970年5月5日的日期对象,即使需要年份为70AD。因此,如果您使用new Date(dateObject)
复制日期对象,那么使用new Date(+dateObject)
将日期强制转换为时间值是一个好主意,而不是让ECMA-262按照自己的方式使用字符串值。虽然您不太可能需要复制0到99AD范围内的日期,但很高兴知道如果尝试的话它会正确工作。
试试这个:
new Date(new Date(1050).getTime()).getTime()
在所有浏览器中都会得到与'1050'相同的结果