Observe que estou baseando todos os meus argumentos em casos de uso do mundo real. Contra-argumentos que não podem ser copiados com um exemplo de uso em aplicativos reais, completos, interessantes e úteis são inválidos. Eu já vi as pequenas "demonstrações de linguagem" que todo mundo já viu, as postagens do blog detalhando como os protótipos e a digitação dinâmica tornam um pequeno exemplo trivial algumas linhas mais curtas do que seria em C #, mas elas simplesmente não são relevantes para os problemas que você encontra ao escrever
código real , em vez de micro-demonstrações e brinquedos. Então, aqui estão minhas queixas com JS:
a) Magia 'isso'. É isso, exceto quando é isso. O JavaScript o leva a usar funções anônimas em todo o lugar, exceto que elas sempre acabam perdendo o contexto apropriado para a variável 'this'; portanto, você acaba tendo um código idiota como "var _this = this" em todo o lugar e depois usando isso dentro de seus retornos de chamada ou outras funções. Alguns dias, juro que o número de funções que consigo escrever que não usam o nome 'this' são realmente menores que o número que o fazem.
b) 1 + "1" - 1 = 10. Além disso, "1" + 0 = "10". Sim, isso realmente causou bugs para nossos aplicativos, onde dados que deveriam ser um número foram carregados de um arquivo JSON como uma string devido a um bug em outro aplicativo e o resultado não foi bom. Todo o nosso código de carregamento teve que ser atualizado para adicionar uma tonelada de conversões de tipo em todo o lugar. Quando eu preciso que algo seja um número, eu realmente quero que seja um número, não uma string ou um objeto ou nulo ou qualquer outra coisa. Lua, que é muito semelhante ao JavaScript na maioria dos aspectos, corrigiu esse problema simplesmente não sendo retardado o suficiente para usar o mesmo operador para adição e concatenação de cadeias.
c) Global por variáveis padrão. Portanto, mesmo se você usar o argumento de que a digitação dinâmica é apenas "mais fácil" porque você não precisa pensar em declarações de variáveis, o JavaScript lança esse argumento pela janela, colocando você 'var' na frente de novos identificadores em todo o lugar . E então ele estraga tudo silenciosamente, se você esquecer.
d) Protótipos em vez de classes. Existem muito poucos aplicativos JavaScript do mundo real em larga escala que não conectam seu próprio sistema de classes para solucionar a inutilidade inerente dos protótipos na arquitetura de aplicativos de grande porte. Esses mesmos aplicativos fazem o uso mínimo de protótipos para estender os tipos JavaScript básicos, e somente porque o JS foi tão mal projetado que até os dois tipos internos interessantes que ele contém estão com metade dos recursos que você espera que eles tenham.
e) Incapacidade de criar tipos de passagem por valor. Este é um problema frequente em praticamente todos os idiomas, exceto o C ++ / D, na verdade. Para aqueles que usam JavaScript para escrever aplicativos WebGL, dê uma olhada em todas as bibliotecas de álgebra linear para JavaScript. Em aplicativos 3D, você quase usa vetores com mais frequência do que escalares. Imagine se todos os números inteiros no seu aplicativo fossem passados por referência, para que "a = 1; b = a; b ++" tornasse ambos aeb iguais a 2. Cada pequeno vetor de três componentes é um objeto completo. Eles são passados por referência (a fonte de quase metade dos erros em nosso jogo WebGL até agora, na verdade). Eles existem em grande quantidade, são alocados no heap e são coletados no lixo, o que exerce uma pressão intensa sobre o GC, o que pode e resulta em pausas no GC, mesmo em jogos WebGL simples, a menos que o desenvolvedor salte por obstáculos ridiculamente complicados para evitar a criação de novos vetores em todos os lugares onde é lógico criar novos vetores. Você não pode sobrecarregar o operador; portanto, você tem expressões muito grandes e feias para executar operações básicas. O acesso a componentes individuais é lento. Os objetos não são compactados de forma nativa e, portanto, são incrivelmente lentos para serem inseridos em um buffer de vértice, a menos que você os implemente como instâncias de Float32Array, o que confunde a porcaria dos otimizadores do V8 e do SpiderMonkey atualmente. Eu mencionei que eles passaram por referência? O acesso a componentes individuais é lento. Os objetos não são compactados de forma nativa e, portanto, são incrivelmente lentos para serem inseridos em um buffer de vértice, a menos que você os implemente como instâncias de Float32Array, o que confunde a porcaria dos otimizadores do V8 e do SpiderMonkey atualmente. Eu mencionei que eles passaram por referência? O acesso a componentes individuais é lento. Os objetos não são compactados de forma nativa e, portanto, são incrivelmente lentos para serem inseridos em um buffer de vértice, a menos que você os implemente como instâncias de Float32Array, o que confunde a porcaria dos otimizadores do V8 e do SpiderMonkey atualmente. Eu mencionei que eles passaram por referência?
f) Nenhum recurso incorporado inclui ou requer funcionalidade. Sério, ainda. Existem bibliotecas de terceiros, mas quase todas elas têm algum tipo de bug ou outro, entre as quais um problema de cache confuso, pelo menos no Chrome, tornando o desenvolvimento real um incômodo.
g) Digitação dinâmica. Sim, estou disposto a iniciar esse argumento. Você começa a perceber isso no momento em que para de escrever pequenos aplicativos ou páginas da Web e começa a escrever grandes aplicativos em que você realmente tem dados que persistem por mais de um único clique do mouse ou ciclo de solicitação / resposta: adicione o tipo errado de objeto a um matriz para processar mais tarde e obter uma falha mais tarde de um membro ou método ausente em um código completamente diferente do local onde estava o erro real. Tempos divertidos. Sim, Java faz a digitação estática parecer ruim. Não, Java / C # / C ++ não é a única maneira de fazer a digitação estática. Inferência de tipo, ligação implícita à interface, etc. oferecem a você todas as vantagens "fáceis de lidar e com poucas pressionamentos de tecla" da digitação dinâmica sem todos os bugs. A segunda linguagem da Web mais popular - o ActionScript 3 - é digitada estaticamente, de fato, apesar de ser idêntica ao JS / ECMAScript. Além disso, recebo mais falhas nos aplicativos Python na área de trabalho do Fedora do que nos aplicativos C / C ++ (na verdade, nenhum dos aplicativos C / C ++ na minha área de trabalho falha, agora que penso nisso). Exceções de membros ausentes == muito mais fáceis de desenvolver e manter aplicativos, certo?
h) velocidade. Sim, houve um esforço ridiculamente imenso por um grande número de desenvolvedores super-durões dedicados aos tempos de execução da linguagem para tornar o JS quase metade da velocidade de um compilador C de baixo nível que um único colegial Junior poderia escrever em poucos meses. E LuaJIT está no mesmo barco que JS em termos de limitações fundamentais de linguagem, mas consegue fazer melhor do que qualquer implementação de JavaScript de qualquer maneira. Pessoas que não entendem o que todas as otimizações JS na V8 ou como realmente fazergostaria de afirmar que o JS pode fazer coisas incríveis em termos de velocidade, mas a realidade é que todas essas otimizações são basicamente "muito difíceis de analisar o código para descobrir tipos de variáveis e compilá-lo como um tipo estaticamente ligeiramente retardado" compilador da linguagem faria isso. " Ah, e há rastreamento, mas o rastreamento também funciona em linguagens de tipo estaticamente (e funciona melhor devido à falta de necessidade de proteção de tipo no código de máquina gerado). Na verdade, nenhuma dessas otimizações de whizbang foi inventada por ou para JS; a maioria foi extraída de JVMs de pesquisa (Java é mau!) ou linguagens clássicas de POO (protótipos são impressionantes!).
i) Não é possível o IntelliSense. Deseja ver quais métodos existem nessa variável que você encontrou na linha 187 do foo.js no seu editor de texto? Que pena. Siga o código até descobrir onde ele foi inicializado e, em seguida, siga o código para descobrir qual o protótipo dele. E espero que não haja código que altere dinamicamente o protótipo nas suas costas. Na verdade, basta executá-lo em um navegador e definir pontos de interrupção, porque descobrir algo útil sobre o valor de qualquer outra maneira é basicamente impossível para qualquer base de código maior que os sites toy_web_app.html que os apologistas do JavaScript usam para glorificar a facilidade e a simplicidade do JavaScript. Alguns editores de código se esforçam muito para fazer melhor, e quase meio que têm sucesso nos casos realmente simples, às vezes uma vez.
j) Nenhuma vantagem. O JavaScript nem é especial se comparado a outra linguagem de tipo dinâmico. Ele não é capaz de fazer nada de interessante, o que também não pode ser feito por Lua, Python, Ruby etc. Nenhuma das implementações de JS é mais rápida que LuaJIT ou PyPy ou várias outras implementações avançadas de JIT de outras dinâmicas. línguas. O JS não possui aspectos positivos em comparação com outros idiomas comumente disponíveis. Ah, exceto que ele roda nativamente em um navegador da Web sem um plug-in. Qual é a única razão no mundo por que é tão popular. De fato, é a única razão pela qual o evento existe. Se alguém há dez anos tivesse pensado ", diabos, vamos colocar uma linguagem bem projetada e estabelecida em nosso navegador e fazer com que os outros façam o mesmo, em vez de fazer com que todos usem esse pequeno truque idiota que o NetScape inventou , "a Web pareceria muito diferente (melhor) hoje. Imagine o futuro se o Chrome inserisse o Python no Chrome como idioma suportado. Ou, na verdade, imagine o seguinte: o Google lança C / C ++ no Chrome como idioma suportado (http://code.google.com/p/nativeclient/).