Uma coisa interessante que me surpreende que ninguém tenha mencionado ainda é a diferença nos tipos de compilação JIT, porque o Flash ainda é compilado por JIT e, na maioria dos navegadores modernos, o JavaScript também é, no entanto, o Flash é uma linguagem fortemente tipada, o que significa existe todo um campo de otimizações que ele pode fazer (como emitir uma chamada para um método diretamente (algo que o JavaScript não pode fazer)), que o JavaScript não pode fazer porque é digitado dinamicamente. Você pode substituir toda a definição de uma função em JavaScript a qualquer momento, e essa nova definição é como deve ser chamada. (ainda é possível para o JavaScript fazer uma chamada indireta que não seria muito mais cara). O acesso ao campo em um campo é realmente um exemplo melhor do que a chamada de método, porque o JavaScript não pode fazer isso indiretamente,
Outra diferença no desempenho é, como já mencionado, o GC. Eu suspeito (não verifiquei) que a maioria dos navegadores usa um GC de contagem de referência (porque toda a memória que o GC alocado para uma página pode ser liberada quando a página é deixada, é realmente um dos melhores lugares para usar um GC de contagem de referência ) ou um GC de varredura conservador (como Boehm). O último pode ser consideravelmente mais lento que o primeiro, se não for implementado corretamente. (Boehm é um exemplo de implementação correta) O Flash, por outro lado, usa um GC preciso (muito mais fácil de fazer em um sistema fortemente tipado). Como o Flash usa um GC preciso, ele não possui a sobrecarga do tempo de execução da contagem de referência. (que não é enorme, mas ainda está lá) Um bom exemplo de um GC preciso é o SGen da Mono, que também compacta os montes.
Depois, chega o fato de que o JavaScript não foi projetado com a animação em mente. (como também foi mencionado) Até onde eu sei, nenhum navegador emitirá instruções no estilo SSE para os loops de animação, onde as funções principais de renderização no Flash provavelmente foram otimizadas manualmente para obter o desempenho máximo. (em alguns lugares sendo gravados em montagem bruta)
Em suma, tudo se resume ao fato de que uma linguagem dinâmica sempre será mais lenta que a de um tipo estaticamente, se tiver que ser compilada em tempo hábil, para não fazer o usuário reclamar da lentidão.