2016-06-21 154 views
109

在Chrome控制檯執行這段代碼:爲什麼typeof null的值在循環內部發生變化?

function foo() { 
 
    return typeof null === 'undefined'; 
 
} 
 
for(var i = 0; i < 1000; i++) console.log(foo());

應打印1000次false,但在某些機器會打印false多次迭代,那麼true爲休息。

enter image description here

這究竟是爲什麼?它只是一個錯誤?

+4

它正在返回1000倍對我來說是真的... –

+2

我認爲它的錯誤,我有262錯誤/ 738真正 –

+1

鉻的控制檯它是奇怪的:如果你推到一個數組並記錄數組,它都是假的'。按原樣,「真實」的數量在鉻中波動。 – dandavis

回答

37

它實際上是一個V8 JavaScript引擎(Wiki)的錯誤。

這臺發動機在鉻,Maxthron,Android操作系統,使用的Node.js等

相對簡單bug description你可以找到在這個Reddit topic

現代JavaScript引擎編譯JS代碼爲優化機代碼 執行(即時編譯)使其運行更快。 但是,優化步驟在 交換中有一些初始性能成本,以便長期加速,所以引擎根據使用的頻率動態決定 是否值得。

在這種情況下,僅在優化路徑中出現錯誤 而未優化路徑正常工作。所以起初該方法的工作原理是 ,但如果它在某個循環中被足夠頻繁地調用,那麼引擎將決定優化它,並用缺陷版本 替換它。

這個bug似乎已經在V8本身(commit)得到修復,藏漢如鉻(bug report)和的NodeJS(commit)。

+0

我確認這個bug仍然在Node.js 6.2.2裏面讓我很擔心。 –

+0

今天(21.06)它已經在V8引擎中修復了,我相信相關的軟件很快就會被更新。 –

+0

將v8修復反向移植到Node.js 6.2.x已經在進行中,因爲[TheAlphaNerd]擁有的問題[#7348](https://github.com/nodejs/node/pull/7348)(https:// github的.com/TheAlphaNerd)。 –

18

爲了回答它爲什麼會發生變化的直接問題,該錯誤發生在Chrome使用的V8 JS引擎的「JIT」優化例程中。起初,代碼完全按照書面形式運行,但運行得越多,優化的好處就越有可能超過分析成本。

在這種情況下,在循環中重複執行後,JIT編譯器會分析該函數,並將其替換爲優化版本。不幸的是,分析做出了不正確的假設,而優化後的版本實際上並沒有產生正確的結果。

具體而言,Reddit user RainHappens suggests它處於型傳播一個錯誤:

它還執行某種類型的傳播(如在什麼類型的變量等即可)。當變量未定義或爲空時,有一種特殊的「不可檢測」類型。在這種情況下,優化雲「null是檢測不到的,所以它可以與被替換‘的比較未定義’串

這是與優化代碼的難題之一:如何保證其具有代碼被重新排布的性能仍然會與原先相同的效果。

相關問題