2015-09-02 13 views
5

La documentazione JS per Date afferma che esistono quattro modi per utilizzare il costruttore Date. Da https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date:Chiamata al costruttore Date con un oggetto Date

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

Tuttavia, sembra che ci sia un quinto modo per utilizzare il costruttore, passando in un oggetto data. Ad esempio, il seguente funziona bene nella console Chrome:

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) 

Si tratta di oggetti diversi, così sembra come un modo semplice per fare una copia di una data:

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) 

Quindi le mie domande sono :

  1. Perché non è presente nella documentazione ufficiale? Mi sto perdendo qualcosa?
  2. È un uso supportato ufficialmente del costruttore? Funzionerà su tutte le piattaforme/browser?
  3. È un modo sicuro di eseguire una copia di un oggetto Date, sostituendo ad es. date2 = new Date().setTime(date.getTime())?
+0

Funziona in Firefox, ma il risultato non è esattamente lo stesso timestamp dell'originale (i millisecondi sono tagliati). Esegui l'esempio alcune volte: [jsfiddle] (https://jsfiddle.net/at51o4aw/) – lzydrmr

risposta

2

Direttamente dalla porzione rilevante del ECMAScript 6 spec:

Se il tipo (valore) è oggetto e il valore ha una scanalatura interna [[DateValue]], poi lasciare tv essere thisTimeValue (valore).

Il che in pratica dice che se si passa il costruttore Data un solo argomento ed è un oggetto e ha la slot interno [[DateValue]], quindi utilizzare tale per inizializzare il nuovo oggetto.

Quindi, quello che stai vedendo è documentato nelle specifiche.

Ecco più in dettaglio:

enter image description here

Ma, la specifica ES5 non è la stessa e farà una conversione in una stringa quando fate quello che stai facendo che sarà poi analizzato come una stringa dal costruttore. Mentre ciò funzionerà per conservare tutto fino ai secondi, non conserverà i millisecondi poiché quelli non sono presenti nella conversione di stringhe predefinita. Quindi, se si desidera una copia perfetta, allora si dovrebbe fare questo in ES5 o precedenti:

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

Molto interessante ... grazie! Quindi il problema è che ho cercato la documentazione sbagliata? Perché l'altra documentazione non spiega questo comportamento? – xph

+0

@xph - MDN non è gospel. È un tentativo di crowdsourcing di aiutare gli sviluppatori (cosa che riesce a fare con successo molto spesso) e io lo uso molto. Ma non è sempre perfetto. Tutta la confusione dovrebbe essere risolta osservando le specifiche effettive. Non so perché questo uso del costruttore non è documentato lì. – jfriend00

+0

Questo comportamento è adottato da tutti i principali browser? O stanno ancora usando il comportamento di ES 5.1? – MinusFour

0

vorrei consigliare contro che per ora. Questo è ciò che sta succedendo ora sotto i browser che seguono specifiche differenti per l'oggetto Date.

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>

lo fa confrontarla perfettamente, ma .... Ecco come ES5.1 gestirà che:

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>

Si ottiene essenzialmente sbarazza dei millisecondi del primo Date oggetto (asserzione potrebbe funzionare se il primo oggetto data non ha millisecondi, eseguire il frammento di un paio di volte). Al momento sembra che Firefox stia seguendo il comportamento di ES5.1 e Chrome ES6.0. Non posso davvero dire quando hanno iniziato ad adottarlo.

non avrei sicuramente consiglio di passare l'oggetto Date come costruzione per una nuova Date oggetto se lo scopo è quello di clonare il primo oggetto Date. Utilizzare invece Data.prototype.getTime().