Tenga en cuenta que estoy basando todos mis argumentos en casos de uso del mundo real. Los contraargumentos que no se pueden respaldar con un ejemplo de uso en aplicaciones reales, completas, interesantes y útiles no son válidos. He visto las pequeñas "demostraciones de lenguaje" que todos los demás tienen, he visto las publicaciones de blog que detallan cómo los prototipos y la escritura dinámica hacen algunos pequeños ejemplos triviales unas pocas líneas más cortas de lo que serían en C #, pero esas simplemente no son relevantes a los problemas con los que te encuentras escribiendo
código real en lugar de micro demos y juguetes. Así que aquí están mis quejas con JS:
a) Magia 'esto'. Esto es esto, excepto cuando esto es eso. JavaScript lo empuja a usar funciones anónimas en todo el lugar, excepto que siempre terminan perdiendo el contexto adecuado para la variable 'this', por lo que terminan teniendo un código tonto como "var _this = this" en todo el lugar y luego usar eso dentro de sus devoluciones de llamada u otras funciones. Algunos días juro que la cantidad de funciones que logro escribir que no usan un 'this' renombrado son en realidad más pequeñas que la cantidad que sí.
b) 1 + "1" - 1 = 10. Además, "1" + 0 = "10". Sí, esto realmente ha causado errores en nuestras aplicaciones, donde los datos que se espera que sean un número se cargaron desde un archivo JSON como una cadena debido a un error en otra aplicación, y el resultado no fue bueno. Todo nuestro código de carga tuvo que actualizarse para agregar una tonelada de conversiones de tipos en todo el lugar. Cuando necesito que algo sea un número, realmente quiero que sea un número, no una cadena o un objeto o un valor nulo o cualquier otra cosa. Lua, que es muy similar a JavaScript en la mayoría de los aspectos, solucionó este problema simplemente al no retrasarse lo suficiente como para usar el mismo operador para la suma y la concatenación de cadenas.
c) Variables globales por defecto. Entonces, incluso si toma el argumento de que la escritura dinámica es simplemente "más fácil" porque no tiene que pensar en declaraciones de variables, JavaScript arroja ese argumento por la ventana al hacer que coloque 'var' delante de nuevos identificadores en todo el lugar . Y luego te atornilla en silencio si te olvidas.
d) Prototipos en lugar de clases. Existen muy pocas aplicaciones de JavaScript del mundo real a gran escala que no conecten su propio sistema de clase para evitar la inutilidad inherente de los prototipos en la arquitectura de aplicaciones grandes. Esas mismas aplicaciones hacen un uso mínimo de los prototipos para extender los tipos básicos de JavaScript, y solo porque JS estaba tan mal diseñado que incluso los dos tipos incorporados interesantes con los que viene carecen de la mitad de las características que esperarías que tengan.
e) Incapacidad para crear tipos de paso por valor. Este es un problema frecuente en casi todos los idiomas, aparte de C ++ / D, en realidad. Para aquellos que usan JavaScript para escribir aplicaciones WebGL, eche un vistazo a todas las bibliotecas de álgebra lineal para JavaScript. En las aplicaciones 3D, casi usas vectores con más frecuencia que los escalares. Imagínese si todos los enteros de su aplicación se pasaron por referencia, de modo que "a = 1; b = a; b ++" hizo que a y b fueran iguales a 2. Cada pequeño vector de tres componentes es un objeto completo completo. Se pasan por referencia (la fuente de casi la mitad de los errores en nuestro juego WebGL hasta ahora, de hecho). Existen en gran cantidad, se asignan a montones y se recolectan basura, lo que ejerce una intensa presión sobre el GC que puede provocar pausas en GC incluso en juegos WebGL simples, a menos que el desarrollador salte a través de aros ridículamente complicados para evitar crear nuevos vectores en todos los lugares donde es lógico crear nuevos vectores. No puede tener una sobrecarga del operador, por lo que tiene expresiones muy grandes y feas para realizar operaciones básicas. El acceso a componentes individuales es lento. Los objetos no están empaquetados de forma nativa y, por lo tanto, son increíblemente lentos para insertarlos en un búfer de vértices, a menos que los implemente como instancias de Float32Array, lo que confunde a los optimizadores de V8 y SpiderMonkey actualmente. ¿Mencioné que fueron aprobados por referencia? El acceso a componentes individuales es lento. Los objetos no están empaquetados de forma nativa y, por lo tanto, son increíblemente lentos para insertarlos en un búfer de vértices, a menos que los implemente como instancias de Float32Array, lo que confunde a los optimizadores de V8 y SpiderMonkey actualmente. ¿Mencioné que fueron aprobados por referencia? El acceso a componentes individuales es lento. Los objetos no están empaquetados de forma nativa y, por lo tanto, son increíblemente lentos para insertarlos en un búfer de vértices, a menos que los implemente como instancias de Float32Array, lo que confunde a los optimizadores de V8 y SpiderMonkey actualmente. ¿Mencioné que fueron aprobados por referencia?
f) Ninguna función incorporada incluye o requiere funcionalidad. En serio, aún. Existen bibliotecas de terceros, pero casi todas tienen algún tipo de error u otro, lo que es un problema de almacenamiento en caché confuso al menos en Chrome, lo que hace que el desarrollo real sea un problema.
g) Escritura dinámica. Sí, estoy dispuesto a comenzar ese argumento. Empiezas a notarlo en el momento en que dejas de escribir pequeñas aplicaciones web o páginas web y comienzas a escribir aplicaciones grandes donde realmente tienes datos que persisten durante más tiempo que un solo clic del mouse o ciclo de solicitud / respuesta: agrega el tipo incorrecto de objeto a un matriz para procesar más tarde y obtener un bloqueo más tarde por un método o miembro que falta en un código completamente diferente de donde estaba el error real. Tiempos divertidos. Sí, Java hace que la escritura estática parezca malvada. No, Java / C # / C ++ no son la única forma de escribir estática. La inferencia de tipos, el enlace de interfaz implícito, etc. le brinda todas las ventajas "fáciles de manejar y no muchas pulsaciones de teclas" de la escritura dinámica sin todos los errores. El segundo lenguaje web más popular, ActionScript 3, se escribe estáticamente, de hecho, a pesar de ser idéntico a JS / ECMAScript. Por otro lado, recibo más bloqueos de las aplicaciones Python en mi escritorio de Fedora que de las aplicaciones C / C ++ (en realidad, ninguna de las aplicaciones C / C ++ en mi escritorio falla, ahora que lo pienso). Faltan excepciones de miembros == es mucho más fácil desarrollar y mantener aplicaciones, ¿verdad?
h) velocidad. Sí, ha habido un esfuerzo ridículamente inmenso por parte de un gran número de desarrolladores súper malos que se dedican a los tiempos de ejecución del lenguaje para hacer que JS sea casi la mitad de rápido que un compilador de C de bajo grado que un solo Junior universitario podría escribir en unos pocos meses. Y LuaJIT está en el mismo barco que JS en términos de limitaciones fundamentales del lenguaje, pero de todos modos logra hacerlo mejor que cualquier implementación de JavaScript. Personas que no entienden cuáles son todas las optimizaciones de JS en V8 o tal hacenMe gusta afirmar que el JS puede hacer cosas asombrosas en cuanto a la velocidad, pero la realidad es que todas esas optimizaciones son básicamente "tratar muy, muy duro, de analizar el código para descubrir tipos de variables y luego compilarlo como un tipo estático ligeramente retrasado el compilador del lenguaje lo haría ". Ah, y hay seguimiento, pero el seguimiento también funciona en lenguajes tipados estáticamente (y funciona mejor debido a la falta de necesidad de protectores de tipo en el código de máquina generado). Ni una sola de esas optimizaciones geniales fue inventada por o para JS, de hecho; la mayoría fueron tomados de JVM de investigación (¡Java es malvado!) o lenguajes clásicos de OOP (¡los prototipos son increíbles!).
i) No IntelliSense incluso posible. ¿Quiere ver qué métodos existen en esa variable que tiene allí en la línea 187 de foo.js en su editor de texto? Demasiado. Vaya a trazar el código hasta que descubra dónde se inicializó, luego siga el código para averiguar qué tiene su prototipo. Y luego espero que no haya código que cambie dinámicamente el prototipo a sus espaldas. De hecho, simplemente ejecútelo en un navegador y establezca puntos de interrupción, porque descubrir cualquier cosa útil sobre el valor de otra manera es básicamente imposible para cualquier base de código más grande que los sitios toy_web_app.html que usan los apologistas de JavaScript para glorificar la facilidad y simplicidad de JavaScript. Algunos editores de código intentan realmente mejorar, y casi tienen éxito para los casos realmente simples, a veces, una vez.
j) Sin ventaja. JavaScript ni siquiera es especial en comparación con otro lenguaje de tipo dinámico. No es capaz de hacer nada interesante que Lua, Python, Ruby, etc. no puedan hacer. Ninguna de las implementaciones de JS es más rápida que LuaJIT o PyPy u otras implementaciones avanzadas de JIT de otras dinámicas. idiomas JS no tiene aspectos positivos en comparación con otros idiomas comúnmente disponibles. Ah, excepto que se ejecuta de forma nativa en un navegador web sin un complemento. Cuál es la única razón en el mundo por la que es tan popular. De hecho, es la única razón por la que existe el evento.. Si alguien hace 10 años hubiera pensado, "diablos, dejemos un lenguaje existente bien diseñado y bien establecido en nuestro navegador y hagamos que los otros muchachos hagan lo mismo en lugar de hacer que todos usen este pequeño truco tonto que se le ocurrió a NetScape , "la Web se vería muy diferente (mejor) hoy. Imagínese el futuro si Chrome dejó caer Python en Chrome como un lenguaje compatible. O, en realidad, imagine esto: Google coloca C / C ++ en Chrome como un idioma compatible (http://code.google.com/p/nativeclient/).