En los browsers el interprete JS comparte el thread de ejecución* con el motor gráfico, lo cual decanta en que se hace una cosa u otra.
Si vos estás interpretando o ejecutando código JS no vas a renderizar/repaintear nada en la UI y viceversa.
*Puede no cumplirse necesariamente en todos los niveles de ejecución.
Luego tenés las diferentes implementaciones de los browsers tanto del interprete como del motor grafico, de las cuales algunas son más rapidas que otras, con lo cual es lógico que no tengan el mismo rendimiento
Con respecto al setTimeout, si vos estás ejecutando una tarea al momento de ejecutar el contenido del setTimeout inevitablemente se te retrasa (recordemos que no podes ejecutar más de una tarea a la vez). Y a esto sumale que el setTimeout recién se ejecuta cuando el interprete esta libre (es decir, termino las tareas inmediatas).
El siguiente código sirve para entender esto ultimo:
Código Javascript
:
Ver original// Diferimos la ejecucion en 0ms
setTimeout(function() {
console.log('DELAYED!');
}, 0);
var d = +new Date;
// Ocupamos el interprete por medio segundo
while(+new Date - d < 500);
// Y luego con un retraso mayor a 500 ms
// "DELAYED!"
EDIT:
Te recomiendo leer
este articulo, que aclara las cosas un poco mejor que este post.