Muito basicamente, em linguagens sem tipo, toda referência aponta para um objeto que contém o tipo e o valor. Por exemplo, var a = 3
aponta para uma instância que contém o valor 3 e o tipo int, se você criar a = "bla"
, a referência é atualizada para uma instância que contém a string "bla" e a string de tipo, o objeto antigo é descartado, etc.
Isso é lento porque toda vez que uma operação (por exemplo a + b
) deve ser feita nesse tipo básico, o tempo de execução deve primeiro desreferenciar os objetos, verificar se seu tipo é compatível, executar a operação, criar um novo objeto.
Por outro lado, a + b
em C ++ ou Java verifica, em tempo de compilação, se os tipos são válidos e compatíveis, aeb são armazenados como valores imediatos (não como referências) e a adição é uma operação simples do processador nesses valores.
Claro, isso é tudo muito teórico. Na prática, muita otimização pode ser feita nesse processo para evitar a maior parte da sobrecarga, e as linguagens dinamicamente tipadas podem ficar bastante rápidas.