O fato de o fechamento anônimo de funções de auto-referência ser tão prevalecente no JavaScript sugere que o JavaScript é uma especificação incompleta? Vemos muito disso:
(function () { /* do cool stuff */ })();
e suponho que tudo é uma questão de gosto, mas isso não parece uma brincadeira, quando tudo que você quer é um espaço para nome privado? O JavaScript não conseguiu implementar pacotes e classes apropriadas?
Compare com o ActionScript 3, também baseado no ECMAScript, onde você obtém
package com.tomauger {
import bar;
class Foo {
public function Foo(){
// etc...
}
public function show(){
// show stuff
}
public function hide(){
// hide stuff
}
// etc...
}
}
Contraste com as convoluções que realizamos em JavaScript (isso, na documentação de criação do plugin jQuery ):
(function( $ ){
var methods = {
init : function( options ) { // THIS },
show : function( ) { // IS },
hide : function( ) { // GOOD },
update : function( content ) { // !!! }
};
$.fn.tooltip = function( method ) {
// Method calling logic
if ( methods[method] ) {
return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
} else if ( typeof method === 'object' || ! method ) {
return methods.init.apply( this, arguments );
} else {
$.error( 'Method ' + method + ' does not exist on jQuery.tooltip' );
}
};
})( jQuery );
Compreendo que essa pergunta possa facilmente se transformar em um discurso retórico sobre preferências e estilos de programação, mas estou realmente muito curioso para saber como os programadores experientes se sentem sobre isso e se é natural, como aprender diferentes idiossincrasias de um novo idioma ou kludgy. , como uma solução alternativa para alguns componentes básicos da linguagem de programação que simplesmente não são implementados?
fonte
Respostas:
A maioria dos comentários argumenta contra o mito de que "protótipos são classes de homens pobres", então repetirei que o OO baseado em protótipo não é inferior ao OO baseado em classe.
O outro ponto "é um erro quando tudo o que você quer é um espaço para nome privado". Você pode se surpreender ao saber que o Scheme usa exatamente o mesmo kludge para definir escopos. Isso não parou de se tornar o exemplo arquetípico do escopo lexical bem feito.
Obviamente, no Scheme, o 'kludge' está escondido atrás das macros ....
fonte
Primeiro, algumas coisas:
Outra maneira de ver o JavaScript é o 1 milhão e o 1 de coisas que você pode fazer com a função como uma construção. Está tudo lá, se você procurar. Apenas nunca está longe de uma função.
Essa coisa de criação de plug-in do jQuery é horrível. Eu não tenho idéia do por que eles estão defendendo isso. As extensões $ devem ser coisas de uso geral que o $ já possui métodos muito bem cobertos, e não o widget construir-me-um-completo-widget. É uma ferramenta de normalização da API do DOM. É melhor usá-lo dentro de seus próprios objetos. Não vejo o apelo de usá-lo como um repositório completo de bibliotecas da interface do usuário.
Pacotes na Web do lado do cliente são inúteis
O que eu pessoalmente não gosto nos pacotes na Web do lado do cliente é que basicamente estaríamos fingindo que estamos fazendo algo que realmente não estamos. Em um mundo pós-.NET, webforms e coisas horríveis que nunca saíram dos nossos amigos Java, eu prefiro pensar em um pedaço de HTML com recursos vinculados como realmente é e não tente apaziguar os desenvolvedores de aplicativos de SO que aprendem coisas novas e resistentes, fingindo que é outra coisa. No JS, na Web do lado do cliente, nada é "importado", exceto quando o Ajax faz algo horrível que opera na ignorância do cache do navegador, o que sim, muitos tentaram fazer. O que importa para o navegador é que ele foi carregado e interpretado ou não. Não temos mais código oculto no cliente em algum lugar disponível para uso "apenas no caso" por boas razões. A primeira é que acabei de descrever as dependências de plug-in e de navegador para aplicativos da web como um fenômeno que geralmente não funcionou muito bem. Queremos web agora. Não após a atualização da Adobe ou da Sun pela terceira vez nesta semana.
A linguagem tem o que precisa para estrutura
Objetos JS são altamente mutáveis. Podemos ter árvores ramificadas de namespaces em qualquer grau que acharmos útil e é muito fácil. Mas sim, para qualquer coisa reutilizável, você precisa manter a raiz de qualquer biblioteca no espaço global. Todas as dependências são vinculadas e carregadas ao mesmo tempo de qualquer maneira, então qual é o sentido de fazer mais alguma coisa? O objetivo de evitar o espaço para nome global não é que haja algo ruim. É muita coisa ruim porque você corre o risco de colisões de namespace ou sobrescrever acidentalmente os principais recursos da linguagem.
Só porque é popular, não significa que estamos fazendo certo
Agora, quando você vir isso em um aplicativo Web do lado do cliente:
O problema não é que não temos ferramentas para estruturar um aplicativo, o problema é que as pessoas não estão avaliando a estrutura. Para sites descartáveis temporários únicos de 2-3 páginas em uma agência de design, eu realmente não tenho problemas com isso. Onde fica feio é quando você precisa criar algo que possa ser mantido, legível e fácil de modificar.
Mas quando você chega ao local em que é hora de implementar todos os objetos e fábricas reutilizáveis e talvez um ou dois novos vars temporários entrem nesse processo, é uma conveniência.
Mas existem implementações de JS com pacotes / módulos
Lembre-se de que no Node.js, onde essas coisas fazem muito mais sentido, elas têm módulos. JS, supondo que possamos evitar o uber-config-hell que atormenta outras linguagens, é a única coisa na equação e cada arquivo executado é seu próprio escopo isolado. Mas em uma página da web, vincular um arquivo js é a própria declaração de importação. Fazer mais importações dinamicamente é apenas um desperdício de tempo e recursos, uma vez que a obtenção dos recursos exige muito mais esforço do que simplesmente adicionar links aos arquivos conforme necessário, sabendo que eles serão armazenados em cache no navegador se outra página precisar deles novamente. Assim, está tentando dividir o espaço global fazendo algo diferente de criar fábricas de objetos adaptadores como jQuery ou objetos mais tradicionais que abrangem um grande subconjunto de tarefas em um determinado domínio enquanto ocupam um lugar no global. Lá'http://wiki.ecmascript.org/doku.php?id=harmony:modules
Portanto, não, não há nada errado com os invocadores automáticos usados para evitar a poluição do espaço de nomes global quando há uma boa razão para usar essas coisas (na maioria das vezes não existe). E temos propriedades equivalentes privadas persistentes em nossos objetos (apenas defina uma var no construtor e não a exponha como uma propriedade).
O fato de podermos fazer essas coisas, no entanto, é impressionante. O uso pesado é um sinal de que os desenvolvedores de JS ainda estão amadurecendo, talvez, mas não é um buraco na linguagem para quem não está tentando forçar um paradigma na Web do lado do cliente que simplesmente não faz sentido aqui.
fonte
A outra coisa que está faltando é que o javscript deve ser compatível com versões anteriores. Se você tentar introduzir a sintaxe do pacote, poderá realmente quebrar a Web de algumas maneiras malucas. Isso seria ruim! Doug Crockford falou sobre isso em vários pontos e por que as tentativas de adicioná-lo falharam.
fonte
Sim, é uma confusão.
Muitas pessoas estão dizendo que "os protótipos não são inferiores às classes". Eu discordo, mas isso é uma questão de preferência. Mas esse nem sequer é o problema real do JavaScript - o problema é que ele foi originalmente projetado como uma linguagem de script rápida e suja para criar itens como botões animados. Em meados dos anos 90, ninguém jamais pensou que o JavaScript seria solicitado a fazer algumas das coisas loucas que está fazendo agora.
fonte
Funções de auto-chamada anônimas são mais parecidas com módulos do que com classes. É irritante que o padrão para javascript seja executado no escopo global. O comitê que trabalha no JS.next está pensando seriamente em adicionar módulos, para que você não coloque suas variáveis locais no escopo global. Felizmente, as funções do Javascript têm uma semântica tão conveniente que podemos usar uma função anônima como um escopo privado com relativa facilidade.
Não vejo como as aulas realmente entram na discussão, exceto que elas são a construção de escopo de nível superior em muitos idiomas. Seria muito bom ter um módulo / pacote / por favor, dê-me-um-escopo-local-para-não-deixar-minhas-variáveis-no-ambiente-global
fonte
Você pode dar uma olhada no ExtJS 3 e 4, onde eles conseguiram implementar os namespaces muito bem.
- adicionado após -1
Meu argumento aqui foi que é possível ocultar todas essas 'convoluções' e ainda ter um código bastante amigável assim:
fonte