Perché il valore di typeof null cambia all'interno di un ciclo?


109

Esecuzione di questo snippet nella console Chrome:

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

dovrebbe stampare 1000 volte false, ma su alcune macchine stamperà falseper un numero di iterazioni, poi trueper il resto.

inserisci qui la descrizione dell'immagine

Perché sta succedendo? È solo un bug?


4
Sta tornando 1000 volte vero per me ...
Hoàng Long,

2
Penso che sia un bug, ho 262 false / 738 true
Jax Teller

1
è qualcosa di strano con la console di Chrome: se esegui il push su un array e ne accedi, è tutto false. così com'è, il numero di trues fluttua in chrome.
dandavis

1
@ HoàngLong come ho detto nella domanda, succede solo su alcune macchine. È anche possibile che accada solo su alcune versioni di Chrome
Agos

2
@ HoàngLong assicurati di eseguirlo in Chrome
Nobita

Risposte:



37

In realtà è un bug del motore JavaScript V8 ( Wiki ).

Questo motore è utilizzato in Chromium, Maxthron, Android OS, Node.js ecc.

Descrizione del bug relativamente semplice che puoi trovare in questo argomento di Reddit :

I moderni motori JavaScript compilano il codice JS in codice macchina ottimizzato quando viene eseguito (compilazione Just In Time) per renderlo più veloce. Tuttavia, la fase di ottimizzazione ha un costo iniziale in termini di prestazioni in cambio di un aumento di velocità a lungo termine, quindi il motore decide dinamicamente se un metodo vale la pena a seconda di quanto comunemente viene utilizzato.

In questo caso sembra esserci un bug solo nel percorso ottimizzato, mentre il percorso non ottimizzato funziona bene. Quindi all'inizio il metodo funziona come previsto, ma se viene chiamato in un ciclo abbastanza spesso a un certo punto il motore deciderà di ottimizzarlo e lo sostituirà con la versione buggy.

Questo bug sembra essere stato corretto nella stessa V8 ( commit ), così come in Chromium ( bug report ) e NodeJS ( commit ).


Ho confermato che il bug è ancora in Node.js 6.2.2, il che mi preoccupa.
Michael Shopsin

È stato risolto nel motore V8 oggi (21.06), credo che presto il software correlato verrà aggiornato.
Sergey Novikov

Il backport della correzione v8 a Node.js 6.2.x è già in corso come problema # 7348 di proprietà di TheAlphaNerd .
Michael Shopsin

18

Per rispondere alla domanda diretta sul perché cambia, il bug è nella routine di ottimizzazione "JIT" del motore V8 JS utilizzato da Chrome. All'inizio, il codice viene eseguito esattamente come scritto, ma più lo si esegue, maggiore è il potenziale che i vantaggi dell'ottimizzazione superano i costi di analisi.

In questo caso, dopo l'esecuzione ripetuta nel ciclo, il compilatore JIT analizza la funzione e la sostituisce con una versione ottimizzata. Sfortunatamente, l'analisi fa un'ipotesi errata e la versione ottimizzata non produce effettivamente il risultato corretto.

In particolare, l' utente di Reddit RainHappens suggerisce che si tratta di un errore nella propagazione del tipo :

Fa anche una certa propagazione dei tipi (come in quali tipi può essere una variabile ecc.). Esiste un tipo speciale "non rilevabile" per quando una variabile è indefinita o nulla. In questo caso l'ottimizzatore diventa "null non è rilevabile, quindi può essere sostituito con la stringa" undefined "per il confronto.

Questo è uno dei problemi più difficili con l'ottimizzazione del codice: come garantire che il codice che è stato riorganizzato per le prestazioni abbia ancora lo stesso effetto dell'originale.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.