2016-09-21 113 views
6

在node.js的V6.0.0爲什麼在for循環之後比for循環之前慢得多?

function testlet() { 
 
\t let a = 0; 
 
\t for (var i = 0; i < 100000000; i++) {} 
 
} 
 

 
function testlet2() { 
 
\t for (var i = 0; i < 100000000; i++) {} 
 
\t let a = 0; 
 
} 
 

 
console.time('let'); 
 
testlet(); 
 
console.timeEnd('let'); 
 

 
console.time('let2'); 
 
testlet2(); 
 
console.timeEnd('let2');

如何在代碼let位置引起如此大的性能差異?

+0

在chrome中的效果相同(沒有驚喜) - 在其他瀏覽器中沒有這樣的差異 –

+0

它也發生在'const'上,但是'var'對於兩者來說都是相同的速度。 – 4castle

+2

奇怪的是,我建議不要擔心太多。微優化是一個移動的目標。今天速度很快,明天可能會很慢。測試下的 –

回答

7

我會採取一個有教養的猜測,並說temporal dead zone是罪魁禍首。

在他的演講中,該循環似乎是您的微基準所關注的內容,即eaten by the optimiser for breakfast作爲Vyacheslav Egorov likes to put it。即使不是這樣,引擎會增加一百萬次變量,但這兩種功能都需要相同的時間。

有什麼不同是當變量a創建。在你的第一個片段中,它在函數的開頭,沒有任何東西在它之前。沒有時間死區,它本質上是一個函數範圍變量;將它改爲var不會有什麼區別(嘗試它)。因此,當函數被調用時,帶有變量的作用域被創建並且該值被初始化爲0,然後一些代碼運行(或不運行)。
相比之下,在第二個片段中有一個時間死區。在聲明let之前的代碼中,訪問a必須拋出異常。所以當函數被調用時,範圍被創建,a的一個插槽被保留,但保持未初始化。在這種狀態下,代碼運行(或不運行),只有在該變量將被初始化並賦值0

因此,如果let處於代碼之中(或之後),範圍更加複雜。這可能會導致優化器以不同的方式對待它,甚至可能影響處於相同範圍內的變量i,或者可能根本無法執行某些優化。