在Chrome控制檯執行這段代碼:爲什麼typeof null的值在循環內部發生變化?
function foo() {
return typeof null === 'undefined';
}
for(var i = 0; i < 1000; i++) console.log(foo());
應打印1000次false
,但在某些機器會打印false
多次迭代,那麼true
爲休息。
這究竟是爲什麼?它只是一個錯誤?
在Chrome控制檯執行這段代碼:爲什麼typeof null的值在循環內部發生變化?
function foo() {
return typeof null === 'undefined';
}
for(var i = 0; i < 1000; i++) console.log(foo());
應打印1000次false
,但在某些機器會打印false
多次迭代,那麼true
爲休息。
這究竟是爲什麼?它只是一個錯誤?
它實際上是一個V8 JavaScript引擎(Wiki)的錯誤。
這臺發動機在鉻,Maxthron,Android操作系統,使用的Node.js等
相對簡單bug description你可以找到在這個Reddit topic:
現代JavaScript引擎編譯JS代碼爲優化機代碼 執行(即時編譯)使其運行更快。 但是,優化步驟在 交換中有一些初始性能成本,以便長期加速,所以引擎根據使用的頻率動態決定 是否值得。
在這種情況下,僅在優化路徑中出現錯誤 而未優化路徑正常工作。所以起初該方法的工作原理是 ,但如果它在某個循環中被足夠頻繁地調用,那麼引擎將決定優化它,並用缺陷版本 替換它。
這個bug似乎已經在V8本身(commit)得到修復,藏漢如鉻(bug report)和的NodeJS(commit)。
我確認這個bug仍然在Node.js 6.2.2裏面讓我很擔心。 –
今天(21.06)它已經在V8引擎中修復了,我相信相關的軟件很快就會被更新。 –
將v8修復反向移植到Node.js 6.2.x已經在進行中,因爲[TheAlphaNerd]擁有的問題[#7348](https://github.com/nodejs/node/pull/7348)(https:// github的.com/TheAlphaNerd)。 –
爲了回答它爲什麼會發生變化的直接問題,該錯誤發生在Chrome使用的V8 JS引擎的「JIT」優化例程中。起初,代碼完全按照書面形式運行,但運行得越多,優化的好處就越有可能超過分析成本。
在這種情況下,在循環中重複執行後,JIT編譯器會分析該函數,並將其替換爲優化版本。不幸的是,分析做出了不正確的假設,而優化後的版本實際上並沒有產生正確的結果。
具體而言,Reddit user RainHappens suggests它處於型傳播一個錯誤:
它還執行某種類型的傳播(如在什麼類型的變量等即可)。當變量未定義或爲空時,有一種特殊的「不可檢測」類型。在這種情況下,優化雲「null是檢測不到的,所以它可以與被替換‘的比較未定義’串
這是與優化代碼的難題之一:如何保證其具有代碼被重新排布的性能仍然會與原先相同的效果。
它正在返回1000倍對我來說是真的... –
我認爲它的錯誤,我有262錯誤/ 738真正 –
鉻的控制檯它是奇怪的:如果你推到一個數組並記錄數組,它都是假的'。按原樣,「真實」的數量在鉻中波動。 – dandavis