admin管理员组

文章数量:1315360

The JS documentation for Date claims that there are four ways to use the Date constructor. From :

new Date();
new Date(value); // integer
new Date(dateString); // string
new Date(year, month[, day[, hour[, minutes[, seconds[, milliseconds]]]]]);

However, there seems to be a fifth way to use the constructor, by passing in a valid date object. For example, the following works fine in the chrome console:

date = new Date() // Wed Sep 02 2015 16:30:21 GMT-0700 (PDT)
date2 = new Date(date) // Wed Sep 02 2015 16:30:21 GMT-0700 (PDT)

They are different objects, so it seems like an easy way to make a copy of a date:

date2 === date // false
date.setMonth(1) // 1422923421090
date // Mon Feb 02 2015 16:30:21 GMT-0800 (PST)
date2 // Wed Sep 02 2015 16:30:21 GMT-0700 (PDT)

So my questions are:

  1. Why is this not in the official documentation? Am I missing something?
  2. Is this an officially supported use of the constructor? Will it work on all platforms/browsers?
  3. Is this a safe way to make a copy of a Date object, replacing e.g. date2 = new Date().setTime(date.getTime())?

The JS documentation for Date claims that there are four ways to use the Date constructor. From https://developer.mozilla/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date:

new Date();
new Date(value); // integer
new Date(dateString); // string
new Date(year, month[, day[, hour[, minutes[, seconds[, milliseconds]]]]]);

However, there seems to be a fifth way to use the constructor, by passing in a valid date object. For example, the following works fine in the chrome console:

date = new Date() // Wed Sep 02 2015 16:30:21 GMT-0700 (PDT)
date2 = new Date(date) // Wed Sep 02 2015 16:30:21 GMT-0700 (PDT)

They are different objects, so it seems like an easy way to make a copy of a date:

date2 === date // false
date.setMonth(1) // 1422923421090
date // Mon Feb 02 2015 16:30:21 GMT-0800 (PST)
date2 // Wed Sep 02 2015 16:30:21 GMT-0700 (PDT)

So my questions are:

  1. Why is this not in the official documentation? Am I missing something?
  2. Is this an officially supported use of the constructor? Will it work on all platforms/browsers?
  3. Is this a safe way to make a copy of a Date object, replacing e.g. date2 = new Date().setTime(date.getTime())?
Share Improve this question asked Sep 2, 2015 at 23:42 xphxph 7525 silver badges16 bronze badges 1
  • It works in Firefox, but the result is not exactly the same timestamp as the original one (milliseconds are cut off). Just run the example a few times: jsfiddle – lzydrmr Commented Sep 2, 2015 at 23:54
Add a ment  | 

2 Answers 2

Reset to default 7

Straight from the relevant portion of the ECMAScript 6 spec:

If Type(value) is Object and value has a [[DateValue]] internal slot, then Let tv be thisTimeValue(value).

Which basically says that if you pass the Date constructor a single argument and it's an object and it has the [[DateValue]] internal slot, then use that to initialize the new object.

So, what you are seeing is documented in the specification.

Here's more detail:

But, the ES5 spec is not the same and will do a conversion to a string when you do what you're doing which will then be parsed as a string by the constructor. While that will work to preserve everything down to the seconds, it will not preserve milliseconds since those are not present in the default string conversion. So, if you want a perfect copy, then you should do this in ES5 or earlier:

var date = new Date();
var date2 = new Date(date.getTime());

I would advise against that for now. This is what's going now under the browsers following different specs for the Date object.

ES 6.0:

var d1 = new Date();
var d2 = new Date(d1.getTime());
//ES6.0 basically gets the property that holds the timestamp straight from the object.

document.getElementById('results').innerHTML = 'Assert: ' + d1.valueOf() + ' === ' + d2.valueOf() + ' ' + (d1.valueOf() === d2.valueOf());
<pre id="results"></pre>

It does pare it perfectly BUT.... Here's how ES5.1 will handle that:

var d1 = new Date();
var d2 = new Date(Date.parse(d1.toString()));
//ES5.1 will attempt to parse the string representation of the Date object.

document.getElementById('results').innerHTML = 'Assert: ' + d1.valueOf() + ' === ' + d2.valueOf() + ' ' + (d1.valueOf() === d2.valueOf());
<pre id="results"></pre>

It basically gets rids of the milliseconds of the first Date object (Assertion might work if the first date object has no milliseconds, run the snippet a couple of times). Firefox seems to be following ES5.1 behaviour at the moment and Chrome ES6.0. Can't really say when they started adopting it.

I would definately not advise to pass the Date object as a constructor for a new Date object if the purpose is to clone the first Date object. Use Data.prototype.getTime() instead.

本文标签: javascriptCalling the Date constructor with a Date objectStack Overflow