Typeof null değeri bir döngü içinde neden değişir?


109

Bu pasajı Chrome konsolunda çalıştırmak:

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

1000 kez yazdırmalıdır false, ancak bazı makinelerde falsebir dizi yineleme ve ardından truegeri kalanı için yazdırılır .

görüntü açıklamasını buraya girin

Bu neden oluyor? Bu sadece bir hata mı?


4
Benim için gerçek 1000 kez geri dönüyor ...
Hoàng Long

2
hata olduğunu düşünüyorum, 262 yanlış / 738 doğru var
Jax Teller

1
Chrome konsolunda garip bir şey var: Bir diziye basarsanız ve diziyi günlüğe kaydederseniz, hepsi bu false. olduğu gibi, truekromda s sayısı dalgalanıyor.
dandavis

1
@ HoàngLong soruda söylediğim gibi, sadece bazı makinelerde oluyor. Bunun yalnızca Chrome'un bazı sürümlerinde olması da mümkündür
Agos

2
@ HoàngLong Chrome'da çalıştırdığınızdan emin olun
Nobita

Yanıtlar:



37

Aslında bir V8 JavaScript motoru ( Wiki ) hatasıdır.

Bu motor Chromium, Maxthron, Android OS, Node.js vb. Uygulamalarda kullanılmaktadır.

Bu Reddit konusunda bulabileceğiniz nispeten basit hata açıklaması :

Modern JavaScript motorları, JS kodunu çalıştırıldığında (Tam Zamanında derleme) daha hızlı çalışmasını sağlamak için optimize edilmiş makine koduna derler. Bununla birlikte, optimizasyon adımının uzun vadeli bir hızlandırma karşılığında bir miktar başlangıç ​​performans maliyeti vardır, bu nedenle motor, ne kadar yaygın kullanıldığına bağlı olarak bir yöntemin buna değip değmeyeceğine dinamik olarak karar verir.

Bu durumda, yalnızca optimize edilmiş yolda bir hata var gibi görünürken, optimize edilmemiş yol iyi çalışır. Bu nedenle, ilk başta yöntem amaçlandığı gibi çalışır, ancak bir noktada yeterince sık bir döngüde çağrılırsa, motor onu optimize etmeye karar verir ve onu buggy sürümüyle değiştirir.

Bu hata , Chromium'da ( hata raporu ) ve NodeJS'de ( commit ) olduğu gibi V8'in kendisinde ( commit ) düzeltilmiş görünüyor .


Hatanın hala Node.js 6.2.2'de olduğunu doğruladım ki bu beni endişelendiriyor.
Michael Shopsin

Bugün (21.06) V8 motorunda düzeltildi, yakında ilgili yazılımın güncelleneceğine inanıyorum.
Sergey Novikov

Node.js 6.2.x için v8 düzeltme Backporting mesele olarak zaten devam ediyor # 7348 aittir TheAlphaNerd .
Michael Shopsin

18

Neden değiştiğiyle ilgili doğrudan soruyu cevaplamak için, hata Chrome tarafından kullanılan V8 JS motorunun "JIT" optimizasyon rutinindedir. İlk başta, kod tam olarak yazıldığı gibi çalıştırılır, ancak onu ne kadar çok çalıştırırsanız, optimizasyonun faydalarının analiz maliyetlerinden daha fazla olma potansiyeli o kadar artar.

Bu durumda, döngüde tekrarlanan yürütmeden sonra, JIT derleyicisi işlevi analiz eder ve onu optimize edilmiş bir sürümle değiştirir. Ne yazık ki, analiz yanlış bir varsayımda bulunuyor ve optimize edilmiş sürüm aslında doğru sonucu üretmiyor.

Özellikle Reddit kullanıcısı RainHappens, bunun tür yayılmasında bir hata olduğunu öne sürüyor :

Aynı zamanda bir tür yayılımı da yapar (bir değişkenin hangi türlerde olabileceği gibi). Bir değişkenin tanımsız veya boş olduğu durumlar için özel bir "saptanamayan" tür vardır. Bu durumda, optimize edici "null tespit edilemez, bu nedenle karşılaştırma için" tanımsız "dizesi ile değiştirilebilir.

Bu, kodu optimize etmenin en zor sorunlarından biridir: performans için yeniden düzenlenen kodun orijinaliyle aynı etkiye sahip olacağı nasıl garanti edilir.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.