¿El hecho de que los cierres anónimos de funciones de autorreferencia sean tan frecuentes en JavaScript sugiere que JavaScript es una especificación incompleta? Vemos mucho de esto:
(function () { /* do cool stuff */ })();
y supongo que todo es cuestión de gustos, pero ¿esto no parece un error, cuando todo lo que quieres es un espacio de nombres privado? ¿No podría JavaScript implementar paquetes y clases adecuadas?
Compare con ActionScript 3, también basado en ECMAScript, donde obtiene
package com.tomauger {
import bar;
class Foo {
public function Foo(){
// etc...
}
public function show(){
// show stuff
}
public function hide(){
// hide stuff
}
// etc...
}
}
Contraste con las convoluciones que realizamos en JavaScript (esto, de la documentación de autoría del complemento 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 );
Aprecio que esta pregunta pueda degenerar fácilmente en una queja sobre las preferencias y los estilos de programación, pero en realidad tengo mucha curiosidad por saber cómo se sienten los programadores experimentados al respecto y si se siente natural, como aprender diferentes idiosincrasias de un nuevo idioma o kludgy , como una solución alternativa a algunos componentes básicos del lenguaje de programación que simplemente no se implementan?
fuente
Respuestas:
La mayoría de los comentarios argumentan en contra del mito de que "los prototipos son clases de hombres pobres", así que solo repetiré que la OO basada en prototipos no es inferior de ninguna manera a la OO basada en clases.
El otro punto "un kludge cuando todo lo que quieres es un espacio de nombres privado". Es posible que se sorprenda al saber que Scheme usa exactamente el mismo kludge para definir los ámbitos. Eso no impidió convertirse en el ejemplo arquetípico del alcance léxico bien hecho.
Por supuesto, en Scheme, el 'kludge' está oculto detrás de las macros ...
fuente
En primer lugar, un par de cosas:
Otra forma de ver JavaScript es las 1 millón y 1 cosas que puede hacer con la función como una construcción. Todo está ahí si lo buscas. Nunca está lejos de ser una función.
Esa creación de plug-in jQuery es horrible. No tengo idea de por qué defienden eso. Las extensiones $ deben ser cosas de uso general que $ ya tiene métodos bastante bien cubiertos, no build-me-a-complete-widget. Es una herramienta de normalización DOM-API. Su uso está mejor enterrado dentro de sus propios objetos. No veo el atractivo de usarlo como un repositorio de biblioteca de interfaz de usuario completo.
Los paquetes en la web del lado del cliente no tienen sentido
Lo que personalmente no me gusta de los paquetes en la web del lado del cliente es que básicamente estaríamos fingiendo que estamos haciendo algo que realmente no hacemos. En una publicación de formularios web .NET y un montón de cosas horribles que nunca se extrajeron de nuestros amigos de Java, prefiero pensar en un trozo de HTML con recursos vinculados como lo que realmente es y no tratar de apaciguar a los desarrolladores de aplicaciones de sistemas operativos resistentes al aprendizaje de nuevas cosas pretendiendo que es otra cosa En JS en la web del lado del cliente, nada se "importa" salvo hacer algo horrible con Ajax que opera en ignorancia del almacenamiento en caché del navegador, lo cual sí, muchos han intentado hacer. Todo lo que le importa al navegador es que se cargó e interpretó o no. No tenemos más código guardado en el cliente en algún lugar disponible para su uso "por si acaso" por buenas razones El n. ° 1 es que acabo de describir las dependencias de un complemento y un complemento de navegador para aplicaciones web como un fenómeno que generalmente no ha funcionado demasiado bien. Queremos web ahora. No después de que Adobe o Sun hayan terminado de actualizar por tercera vez esta semana.
El lenguaje tiene lo que necesita para estructurarse
Los objetos JS son altamente mutables. Podemos tener árboles ramificados de espacios de nombres en cualquier grado que nos resulte útil y es muy fácil hacerlo. Pero sí, para cualquier cosa reutilizable, debe pegar la raíz de cualquier biblioteca en el espacio global. Todas las dependencias están vinculadas y cargadas al mismo tiempo de todos modos, entonces, ¿qué sentido tiene hacer algo más? El punto de evitar el espacio de nombres global no es que haya nada malo. Es que demasiadas cosas son malas porque corres el riesgo de colisiones en el espacio de nombres o sobreescribiendo accidentalmente las características principales del lenguaje.
Solo porque sea popular no significa que lo estamos haciendo bien
Ahora, cuando vea esto en una aplicación web del lado del cliente:
El problema no es que nos falten herramientas para estructurar una aplicación, sino que la gente no está valorando la estructura. En el caso de sitios temporales desechables únicos de 2-3 páginas en una agencia de diseño, realmente no tengo ningún problema con eso. Donde se pone feo es cuando tienes que construir algo que se pueda mantener y que sea legible y fácil de modificar.
Pero cuando llegue al lugar donde es hora de implementar todos los objetos y fábricas reutilizables y tal vez uno o dos nuevos vars temporales puedan ingresar en ese proceso, es una conveniencia.
Pero hay implementaciones de JS con paquetes / módulos
Tenga en cuenta que en Node.js, donde tales cosas tienen mucho más sentido, tienen módulos. JS, suponiendo que podamos evitar uber-config-hell que plaga otros idiomas, es lo único en la ecuación y cada archivo ejecutado es su propio alcance aislado. Pero en una página web, vincular un archivo js es en sí mismo la declaración de importación. Hacer más importaciones sobre la marcha es solo una pérdida de tiempo y recursos, ya que obtener los recursos requiere mucho más esfuerzo que simplemente agregar enlaces a los archivos, ya que los necesita sabiendo que se almacenarán en caché en un navegador si otra página los necesita nuevamente. Por lo tanto, está tratando de dividir el espacio global haciendo algo más que crear fábricas de objetos adaptadores como jQuery u objetos más tradicionales que cubren un gran subconjunto de tareas en un dominio dado mientras ocupan un lugar en global. Allí'http://wiki.ecmascript.org/doku.php?id=harmony:modules
Entonces, no, no hay nada de malo en que los invocadores automáticos se usen para evitar la contaminación global del espacio de nombres cuando hay una buena razón para usar tales cosas (la mayoría de las veces no lo hay). Y tenemos propiedades persistentes privadas equivalentes en nuestros objetos (solo defina una var en el constructor y no la exponga como una propiedad).
Sin embargo, el hecho de que PODEMOS hacer tales cosas es increíble. El uso intensivo es una señal de que los desarrolladores de JS todavía están madurando, pero no es un agujero en el lenguaje para cualquiera que no esté tratando de forzar un paradigma en la web del lado del cliente que simplemente no tiene sentido aquí.
fuente
La otra cosa que falta es que javscript debe ser compatible con versiones anteriores. Si intenta introducir la sintaxis del paquete, realmente podría romper la web de alguna manera loca. ¡Eso sería malo! Doug Crockford ha hablado sobre esto en varios puntos y por qué los intentos de agregarlo han fallado.
fuente
Sí, es un error.
Mucha gente dice que "los prototipos no son inferiores a las clases". No estoy de acuerdo, pero eso es una cuestión de preferencia. Pero ese ni siquiera es el verdadero problema con JavaScript: el problema es que fue originalmente diseñado como un lenguaje de script rápido y sucio para crear cosas como botones animados. A mediados de los 90, nadie pensó que se le pediría a JavaScript que hiciera algunas de las locuras que está haciendo ahora.
fuente
Las funciones anónimas de auto invocación son más parecidas a los módulos que a las clases. Es molesto que el valor predeterminado para javascript sea ejecutarse en el ámbito global. El comité que trabaja en JS.next está considerando seriamente agregar módulos, de modo que no deje caer sus variables locales en el ámbito global. Afortunadamente, las funciones de Javascript tienen una semántica tan conveniente que podemos usar una función anónima como un ámbito privado con relativa facilidad.
No veo cómo las clases realmente entran en la discusión en absoluto, excepto que son la construcción de alcance de nivel superior en muchos idiomas. Sería muy bueno tener una mejor construcción de módulo / paquete / please-give-me-a-local-scope-so-i-don't-leave-my-variables-in-the-global-environment.
fuente
Es posible que desee echar un vistazo a ExtJS 3 y 4, donde han logrado implementar espacios de nombres bastante bien.
- agregado después de -1
Mi punto aquí fue que es posible ocultar todas estas 'circunvoluciones' y aún así tener un código bastante amigable como este:
fuente