¿Por qué cambia el valor de typeof null dentro de un bucle?

109

Ejecutando este fragmento en la consola de Chrome:

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

debería imprimir 1000 veces false, pero en algunas máquinas se imprimirá falsepara varias iteraciones, luego truepara el resto.

ingrese la descripción de la imagen aquí

¿Por qué está pasando esto? ¿Es solo un error?

Agos
fuente
4
Está volviendo 1000 veces cierto para mí ...
Hoàng Long
2
Creo que es un error, tengo 262 falsos / 738 verdaderos
Jax Teller
1
es algo extraño con la consola de Chrome: si empuja a una matriz y registra la matriz, es todo false. tal cual, el número de trues fluctúa en Chrome.
dandavis
1
@ HoàngLong como dije en la pregunta, solo ocurre en algunas máquinas. También es posible que suceda solo en algunas versiones de Chrome
Agos
2
@ HoàngLong asegúrese de ejecutarlo en Chrome
Nobita

Respuestas:

37

En realidad, es un error del motor V8 JavaScript ( Wiki ).

Este motor se utiliza en Chromium, Maxthron, Android OS, Node.js, etc.

Puede encontrar una descripción de error relativamente simple en este tema de Reddit :

Los motores JavaScript modernos compilan código JS en código de máquina optimizado cuando se ejecuta (compilación Just In Time) para que se ejecute más rápido. Sin embargo, el paso de optimización tiene un costo de rendimiento inicial a cambio de una aceleración a largo plazo, por lo que el motor decide dinámicamente si un método vale la pena dependiendo de la frecuencia con la que se use.

En este caso, parece haber un error solo en la ruta optimizada, mientras que la ruta no optimizada funciona bien. Entonces, al principio, el método funciona según lo previsto, pero si se llama en un bucle con la suficiente frecuencia en algún momento, el motor decidirá optimizarlo y reemplazarlo con la versión con errores.

Este error parece haberse solucionado en la propia V8 ( confirmación ), así como en Chromium ( informe de error ) y NodeJS ( confirmación ).

Sergey Novikov
fuente
Confirmé que el error todavía está en Node.js 6.2.2, lo que me preocupa.
Michael Shops el
Se corrigió en el motor V8 hoy (21.06), creo que pronto se actualizará el software relacionado.
Sergey Novikov
La actualización de la corrección v8 a Node.js 6.2.x ya está en curso como el problema # 7348 propiedad de TheAlphaNerd .
Michael Shops el
18

Para responder a la pregunta directa de por qué cambia, el error está en la rutina de optimización "JIT" del motor V8 JS utilizado por Chrome. Al principio, el código se ejecuta exactamente como está escrito, pero cuanto más lo ejecuta, más posibilidades hay de que los beneficios de la optimización superen los costos del análisis.

En este caso, después de la ejecución repetida en el bucle, el compilador JIT analiza la función y la reemplaza con una versión optimizada. Desafortunadamente, el análisis hace una suposición incorrecta y la versión optimizada no produce el resultado correcto.

Específicamente, el usuario de Reddit RainHappens sugiere que se trata de un error en la propagación de tipos :

También hace algún tipo de propagación (como en qué tipos puede ser una variable, etc.). Hay un tipo especial "indetectable" para cuando una variable no está definida o es nula. En este caso, el optimizador pasa a "nulo es indetectable, por lo que se puede reemplazar con la cadena" indefinida "para la comparación.

Este es uno de los problemas difíciles con la optimización del código: cómo garantizar que el código que se ha reorganizado para el rendimiento seguirá teniendo el mismo efecto que el original.

IMSoP
fuente