Existem cerca de cem problemas de terminologia aqui, a maioria criada em torno de alguém (não você) tentando fazer com que a ideia deles pareça o melhor.
Todas as linguagens orientadas a objetos precisam ser capazes de lidar com vários conceitos:
- encapsulamento de dados junto com operações associadas nos dados, conhecidas como membros de dados e funções de membros ou dados e métodos, entre outras coisas.
- herança, a capacidade de dizer que esses objetos são exatamente como aquele outro conjunto de objetos, EXCETO essas mudanças
- polimorfismo ("muitas formas") no qual um objeto decide por si mesmo quais métodos devem ser executados, para que você possa depender do idioma para rotear suas solicitações corretamente.
Agora, na comparação:
A primeira coisa é toda a pergunta "classe" vs "protótipo". A idéia começou originalmente em Simula, onde, com um método baseado em classe, cada classe representava um conjunto de objetos que compartilhavam o mesmo espaço de estado (leia "valores possíveis") e as mesmas operações, formando assim uma classe de equivalência. Se você olhar para Smalltalk, como é possível abrir uma classe e adicionar métodos, é efetivamente o mesmo que você pode fazer em Javascript.
As linguagens OO posteriores queriam poder usar a verificação de tipo estático, então obtivemos a noção de uma classe fixa definida em tempo de compilação. Na versão de classe aberta, você tinha mais flexibilidade; na versão mais recente, você tinha a capacidade de verificar alguns tipos de correção no compilador que, de outra forma, exigiriam testes.
Em uma linguagem "baseada em classe", essa cópia ocorre no momento da compilação. Em uma linguagem de protótipo, as operações são armazenadas na estrutura de dados do protótipo, que é copiada e modificada no tempo de execução. Abstratamente, porém, uma classe ainda é a classe de equivalência de todos os objetos que compartilham o mesmo espaço de estado e métodos. Ao adicionar um método ao protótipo, você efetivamente cria um elemento de uma nova classe de equivalência.
Agora, por que isso? principalmente porque cria um mecanismo simples, lógico e elegante em tempo de execução. agora, para criar um novo objeto ou para criar uma nova classe, basta executar uma cópia profunda, copiando todos os dados e a estrutura de dados do protótipo. Você obtém herança e polimorfismo mais ou menos de graça, então: a pesquisa de método sempre consiste em solicitar a um dicionário uma implementação de método por nome.
O motivo que acabou no script Javascript / ECMA é basicamente que, quando começamos com isso há 10 anos, estávamos lidando com computadores muito menos potentes e navegadores muito menos sofisticados. Escolher o método baseado em protótipo significava que o intérprete poderia ser muito simples, preservando as propriedades desejáveis da orientação a objetos.