假设有var o = {a:Date.now(), b:Date.now()}
。
o.a === o.b
是否总是true
?(我主要关心Node.JS。)
假设有var o = {a:Date.now(), b:Date.now()}
。
o.a === o.b
是否总是true
?(我主要关心Node.JS。)
不管规范怎么说,Date.now
可以在运行时被用户自定义的函数替换。这在 Node 和浏览器中都适用:
let oldNow = Date.now;
Date.now = function () {
let wait = oldNow() + 1000;
while (oldNow() < wait) {
// wait one second
}
return oldNow();
}
有了这个设定,每个调用至少需要一秒钟,因此你的两次调用将永远不相等。
当我们查看Date.now
规范 (15.9.4.4)时,它只是简单地说它返回
指定调用 now 时刻的 UTC 日期和时间的时间值。
这并不能保证两个调用会返回相同的值。从我所知道的来看,规范指定Date
对象具有毫秒精度 (15.9.1.1),但对准确性没有任何保证。
由于底层计时器不精确并且两个调用在同一个滴答中发生,因此很可能在同一行中进行两个调用将大概率返回相同的时间,但规范似乎没有指定。
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 !=');
}
}
And you will see what happen !
performance.now()
我可以得到这两个值的差异!谢谢。 - Randomblue不。
你的问题中隐含了两个问题:
对象初始化器是否有特殊的功能,可以查看属性初始化值并对其进行“优化”或其他操作以避免冗余调用?
在快速连续调用两次Date.now
时,它们返回的值是否总是相同的?
答案是不会,不会。 :-) 让我们更详细地看一下:
对象初始化器是逐步处理的。这在规范中有详细说明(从这里开始),虽然在之前的第5版规范中更容易理解,但基本上它说对象会被创建,然后按照源代码顺序一个接一个地添加属性。所以有:
var o = {
a: "one",
b: "two"
};
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
可靠地获得 0
,b
可靠地获得 1
。因此,我们知道在这种情况下:"var o = {
a: Date.now(),
b: Date.now()
};
在快速连续调用“Date.now”时,会进行两次调用,这两次调用可能会返回不同的值。这是一个基于时间的函数,如果你在毫秒级别的时间变化前后进行调用,就会得到不同的值。虽然对于计算机来说,一毫秒是很长的时间,但也不是非常长。
我们可以通过实验证明它确实会发生:
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>
counter
通常并不是很高(通常为4位数字,有时为3位,有时为5位)。(我的强调) 因此,符合规范的实现不能在开始JavaScript“任务”之前决定
now
函数返回一个数字值,该数字值指定了UTC日期和时间的时间值,即“现在”的发生时间。
now
的值,然后在整个任务中重复使用它。这与规范相违背。
Date.now
,我们也知道两次Date.now
可能返回不同的值,因此我们知道对于var o = {a:Date.now(), b:Date.now()}
,在遵循规范的任何JavaScript引擎(例如NodeJS(V8)),o.a === o.b
并不总是为真。
Date.now
可能返回两个不同的值(尽管有一段时间,Omniture 中使用了非常相似的代码,导致了许多问题)。 - ssube