javascript - new - Dos Date.now() en una declaración de objeto
timestamp javascript (5)
Incluso si los dos podrían ser siempre iguales en cuanto a la implementación del motor JS, lógicamente son dos instantes de tiempo diferentes y así es como los trataría.
Sea var o = {a:Date.now(), b:Date.now()}
.
¿Es o oa === ob
siempre true
? (Estoy más interesado en Node.JS.)
No, prueba esta simple prueba:
var test = new Array();
for(var i=0; i<40000; i++){
test.push({a:Date.now(), b:Date.now()});
}
for(var i=0 ; i<test.length; i++){
if(test[i].a != test[i].b){
console.warn(''a & b !='');
}
}
¡Y verás qué pasa!
No.
Antes de que lleguemos a lo que podría decir la especificación, Date.now
puede reemplazarse con una función definida por el usuario en el tiempo de ejecución. Esto funciona tanto en el nodo como en los navegadores:
let oldNow = Date.now;
Date.now = function () {
let wait = oldNow() + 1000;
while (oldNow() < wait) {
// wait one second
}
return oldNow();
}
Con eso, cada invocación tomará al menos un segundo, por lo que sus dos llamadas nunca serán iguales.
Cuando miramos la especificación de Date.now
(15.9.4.4) , simplemente dice que devuelve
el valor de tiempo que designa la fecha y hora UTC de la aparición de la llamada a ahora
lo que no proporciona garantías para que dos llamadas devuelvan el mismo valor. Por lo que puedo decir, la especificación especifica que los objetos Date
tendrán una precisión de milisegundos (15.9.1.1) pero no ofrecen ninguna garantía en cuanto a la precisión.
Es probable que dos llamadas en la misma línea retornen al mismo tiempo, debido a que el temporizador subyacente es impreciso y las dos ocurren dentro de la misma marca, pero la especificación no parece especificar eso.
No.
Hay dos preguntas implícitas en tu pregunta:
¿Hay algo especial en los inicializadores de objetos que analice los valores del inicializador de propiedades y los "optimice" o algo para evitar llamadas redundantes?
¿
Date.now
siempre devolverá el mismo valor cuando se lo llama dos veces en rápida sucesión?
Las respuestas son no, y no. :-) Veamos con más detalle:
Inicializadores de objetos
Los inicializadores de objetos se manejan paso a paso. Esto se detalla en la especificación ( comience aquí ), y aunque fue mucho más fácil de entender en la especificación de la quinta edición anterior, básicamente dice que el objeto se crea y luego las propiedades se agregan en el orden del código fuente , una en un momento. Así que con:
var o = {
a: "one",
b: "two"
};
Primero, el motor de JavaScript crea el objeto, luego evalúa el lado derecho del inicializador de propiedades para a
( "one"
), agrega la propiedad a con el valor resultante, luego evalúa el lado derecho del inicializador de propiedades para b
( "two"
), luego agrega la propiedad b
con el valor resultante. Por lo tanto, sabemos que los lados derechos se evalúan por separado y en distintos momentos del proceso. Es por eso que con esto:
var value = 0;
function unique() {
return value++;
}
var o = {
a: unique(),
b: unique()
};
var value = 0;
function unique() {
return value++;
}
var o = {
a: unique(),
b: unique()
};
snippet.log("o.a = " + o.a + ", o.b = " + o.b);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
... a
confiablemente obtiene 0
y b
confiablemente obtiene 1
.
En consecuencia, sabemos que con:
var o = {
a: Date.now(),
b: Date.now()
};
... se Date.now
dos llamadas a Date.now
. Date.now
, una después de la otra, en rápida sucesión. Es hora de mirar eso ...
Date.now
llama en rápida sucesión
Dos llamadas a Date.now
, una detrás de otra, pueden devolver valores diferentes; Ni siquiera es tan raro. Es una función basada en el tiempo. Si llama a cualquier lado de un cambio de tiempo de milisegundos, obtendrá valores diferentes. Ahora, un milisegundo es mucho tiempo para una computadora, pero no tanto.
Fácilmente podemos probar que sucede empíricamente:
var first, second;
var counter = 0;
snippet.log("Start");
do {
first = Date.now();
second = Date.now();
++counter;
} while (first === second);
snippet.log("Stop, values were different: " + first + " !== " + second + "; counter = " + counter);
var first, second;
var counter = 0;
snippet.log("Start");
do {
first = Date.now();
second = Date.now();
++counter;
} while (first === second);
snippet.log("Stop, values were different");
snippet.log(first + " !== " + second);
snippet.log("counter = " + counter);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Lo anterior siempre se detiene, demostrando que dos llamadas en rápida sucesión devolverán valores diferentes. Para mí, en Chrome en Linux, el counter
no suele ser tan alto (normalmente 4 dígitos, a veces 3, a veces 5).
También sabemos que sucede a partir de la especificación , que dice:
La función
now
devuelve un valor Número que es el valor de tiempo que designa la fecha y hora UTC de la aparición de la llamada anow
.
(mi énfasis) Una implementación que cumpla con la especificación no puede, por lo tanto, decidir antes de iniciar un " job " de JavaScript cuál será el valor de now
y luego reutilizarlo en todo el trabajo. Eso sería contrario a la especificación.
Conclusión
Como sabemos que los inicializadores de propiedades en el inicializador de objetos se procesan uno tras otro y que se realizan dos llamadas separadas a Date.now
, y sabemos que dos llamadas a Date.now
pueden devolver valores diferentes, sabemos que para var o = {a:Date.now(), b:Date.now()}
, oa === ob
no siempre será verdad, en NodeJS (por ejemplo, V8) o cualquier otro motor de JavaScript que siga la especificación.
Si está interesado en la precisión, sugeriría performance.now (). Si necesita que sean iguales, sugeriría escribir un constructor para el objeto, luego asignar Date.now () a una variable temporal, y luego asignar ese valor a ay b.
Aquí hay una introducción a la API Discovering the HR Time API
Aquí hay alguna información específica del nodo : Nodo hrtime