Beachten Sie, dass ich alle meine Argumente auf reale Anwendungsfälle stütze. Gegenargumente, die nicht mit einem Anwendungsbeispiel in einer echten, vollständigen, interessanten, nützlichen Anwendung belegt werden können, sind ungültig. Ich habe die kleinen "Sprachdemos" gesehen, die alle anderen haben. Ich habe die Blog-Posts gesehen, die beschreiben, wie Prototypen und dynamisches Tippen ein triviales kleines Beispiel ein paar Zeilen kürzer machen als in C #, aber diese sind einfach nicht relevant zu den Problemen, die beim Schreiben von echtem
Code auftreten, anstatt von Mikrodemos und Spielzeug. Also hier sind meine Probleme mit JS:
a) Magie 'das'. Dies ist dies, außer wenn dies das ist. JavaScript zwingt Sie dazu, überall anonyme Funktionen zu verwenden, außer dass sie immer den richtigen Kontext für die 'this'-Variable verlieren, sodass Sie am Ende überall doof Code wie "var _this = this" haben und diesen dann verwenden in Ihren Rückrufen oder anderen Funktionen. An manchen Tagen schwöre ich, dass die Anzahl der Funktionen, die ich schreiben kann und die kein umbenanntes "dies" verwenden, tatsächlich kleiner ist als die Anzahl, die dies tut.
b) 1 + "1" - 1 = 10. Auch "1" + 0 = "10". Ja, dies hat tatsächlich zu Fehlern in unseren Anwendungen geführt, bei denen Daten, von denen erwartet wird, dass sie eine Zahl sind, aufgrund eines Fehlers in einer anderen Anwendung aus einer JSON-Datei als Zeichenfolge geladen wurden und das Ergebnis nicht gut war. Alle unsere Ladecodes mussten aktualisiert werden, um überall eine Menge Typkonvertierungen hinzuzufügen. Wenn ich etwas brauche, um eine Zahl zu sein, möchte ich unbedingt, dass es eine Zahl ist, keine Zeichenfolge, kein Objekt, keine Null oder irgendetwas anderes. Lua, das JavaScript in den meisten Punkten sehr ähnlich ist, hat dieses Problem behoben, indem es nicht verzögert genug war, um denselben Operator für das Hinzufügen und die Verkettung von Zeichenfolgen zu verwenden.
c) Standardmäßig globale Variablen. Selbst wenn Sie das Argument annehmen, dass die dynamische Eingabe nur "einfacher" ist, weil Sie nicht über Variablendeklarationen nachdenken müssen, wirft JavaScript dieses Argument aus dem Fenster, indem Sie "var" überall vor neue Bezeichner setzen . Und dann nervt es dich, wenn du es vergisst.
d) Prototypen statt Klassen. Es gibt nur sehr wenige realistische JavaScript-Anwendungen in großem Maßstab, die kein eigenes Klassensystem einbinden, um die inhärente Nutzlosigkeit von Prototypen in großen Anwendungsarchitekturen zu umgehen. Dieselben Apps nutzen Prototypen nur minimal, um die JavaScript-Basistypen zu erweitern, und dies nur, weil JS so schlecht entworfen wurde, dass selbst den beiden interessanten integrierten Typen die Hälfte der Funktionen fehlt, die Sie von ihnen erwarten würden.
e) Unfähigkeit, Typen mit vorbeigehenden Werten zu erstellen. Abgesehen von C ++ / D ist dies ein häufiges Problem in nahezu jeder Sprache. Wer JavaScript zum Schreiben von WebGL-Apps verwendet, sollte sich alle linearen Algebra-Bibliotheken für JavaScript ansehen. In 3D-Apps verwenden Sie Vektoren fast häufiger als Skalare. Stellen Sie sich vor, jede Ganzzahl in Ihrer App würde als Referenz übergeben, sodass "a = 1; b = a; b ++" sowohl a als auch b gleich 2 macht. Jeder kleine Vektor mit drei Komponenten ist ein vollständiges vollständiges Objekt. Sie werden als Referenz weitergegeben (die Quelle von fast der Hälfte der Fehler in unserem WebGL-Spiel). Sie sind in großer Menge vorhanden, werden auf Haufen verteilt und werden durch Müll eingesammelt. Dadurch wird der GC stark unter Druck gesetzt, was selbst in einfachen WebGL-Spielen zu GC-Pausen führen kann und muss. es sei denn, der Entwickler springt durch lächerlich komplizierte Rahmen, um das Erstellen neuer Vektoren an allen Stellen zu vermeiden, an denen es logisch ist, neue Vektoren zu erstellen. Sie können den Operator nicht überladen, daher haben Sie sehr große und hässliche Ausdrücke, um grundlegende Operationen auszuführen. Der Zugriff auf einzelne Komponenten ist langsam. Die Objekte sind nicht nativ gepackt und daher unglaublich langsam in einen Vertex-Puffer zu verschieben, es sei denn, Sie implementieren sie als Float32Array-Instanzen, was die Optimierer von V8 und SpiderMonkey derzeit durcheinander bringt. Habe ich erwähnt, dass sie als Referenz übergeben wurden? Der Zugriff auf einzelne Komponenten ist langsam. Die Objekte sind nicht nativ gepackt und daher unglaublich langsam in einen Vertex-Puffer zu verschieben, es sei denn, Sie implementieren sie als Float32Array-Instanzen, was die Optimierer von V8 und SpiderMonkey derzeit durcheinander bringt. Habe ich erwähnt, dass sie als Referenz übergeben wurden? Der Zugriff auf einzelne Komponenten ist langsam. Die Objekte sind nicht nativ gepackt und daher unglaublich langsam in einen Vertex-Puffer zu verschieben, es sei denn, Sie implementieren sie als Float32Array-Instanzen, was die Optimierer von V8 und SpiderMonkey derzeit durcheinander bringt. Habe ich erwähnt, dass sie als Referenz übergeben wurden?
f) Keine eingebauten Funktionen enthalten oder erfordern. Ernsthaft noch. Es gibt Bibliotheken von Drittanbietern, aber fast alle haben die eine oder andere Art von Fehler, von denen nicht zuletzt ein verwirrendes Caching-Problem in mindestens Chrome vorliegt, das die eigentliche Entwicklung zu einem Ärgernis macht.
g) Dynamische Eingabe. Ja, ich bin bereit, dieses Argument zu beginnen. Sie bemerken es am schnellsten, wenn Sie aufhören, kleine Web-Apps oder Webseiten zu schreiben, und Sie beginnen, große Apps zu schreiben, in denen Daten vorhanden sind, die länger als ein einziger Mausklick oder ein Anforderungs- / Antwortzyklus bestehen: Fügen Sie einem Objekt die falsche Art hinzu Array, um es später zu verarbeiten und einen Absturz von einer fehlenden Methode oder einem fehlenden Member in einem völlig anderen Code als dem, in dem sich der eigentliche Fehler befand, zu erhalten. Lustige Zeiten. Ja, Java lässt statisches Tippen böse erscheinen. Nein, Java / C # / C ++ ist nicht die einzige Möglichkeit, statisch zu tippen. Typinferenz, implizite Schnittstellenbindung usw. bieten Ihnen alle Vorteile des dynamischen Tippens ohne alle Fehler, die Sie mit wenigen Tastenanschlägen erzielen können. Die zweitbeliebteste Web-Sprache - ActionScript 3 - ist statisch geschrieben, obwohl sie ansonsten mit JS / ECMAScript identisch ist. Abgesehen davon stürzen die Python-Apps auf meinem Fedora-Desktop mehr ab als die C / C ++ - Apps (eigentlich stürzt keine der C / C ++ - Apps auf meinem Desktop ab, wenn ich darüber nachdenke). Fehlende Mitgliedsausnahmen == So viel einfacher, Apps zu entwickeln und zu warten, oder?
h) Geschwindigkeit. Ja, es gab einige lächerlich große Anstrengungen von einer großen Anzahl von super-bösen Entwicklern, die in die Sprachlaufzeiten gesteckt wurden, um JS fast halb so schnell zu machen wie einen Low-Grade-C-Compiler, den ein einzelner College-Junior in wenigen schreiben konnte Monate. Und LuaJIT ist in Bezug auf grundlegende Sprachbeschränkungen mit JS identisch, schafft es aber trotzdem, eine bessere Leistung als jede JavaScript-Implementierung zu erbringen. Leute, die nicht verstehen, was alle JS-Optimierungen in V8 oder so tatsächlich tunIch würde gerne behaupten, der JS kann erstaunliche Dinge in Bezug auf die Geschwindigkeit tun, aber die Realität ist, dass all diese Optimierungen im Grunde genommen nur "sehr sehr bemüht sind, den Code zu analysieren, um Typen für Variablen herauszufinden und ihn dann wie einen leicht verzögerten statisch getippten Code zu kompilieren Der Compiler der Sprache würde es tun. " Oh, und es gibt eine Ablaufverfolgung, aber dann funktioniert die Ablaufverfolgung auch für statisch typisierte Sprachen (und funktioniert besser, weil im generierten Maschinencode keine Typschutzeinrichtungen erforderlich sind). Tatsächlich wurde keine einzige dieser Whizbang-Optimierungen von oder für JS erfunden. Die meisten stammen aus Forschungs-JVMs (Java ist böse!) oder klassischen OOP-Sprachen (Prototypen sind fantastisch!).
i) Kein IntelliSense möglich. Möchten Sie sehen, welche Methoden für die Variable existieren, die Sie in Zeile 187 von foo.js in Ihrem Texteditor haben? Schade. Gehen Sie den Code durch, bis Sie herausgefunden haben, wo er initialisiert wurde, und gehen Sie dann den Code durch, um herauszufinden, welchen Prototyp er enthält. Und dann hoffe ich, dass es keinen Code gibt, der den Prototypen dynamisch hinter Ihrem Rücken verändert. Führen Sie es einfach in einem Browser aus und legen Sie Haltepunkte fest, da es für eine Codebasis, die größer ist als die toy_web_app.html-Sites, die JavaScript-Apologeten verwenden, grundsätzlich unmöglich ist, nützliche Informationen über den Wert auf andere Weise zu erhalten, um die Benutzerfreundlichkeit und Einfachheit von JavaScript zu verherrlichen. Einige Code-Editoren sind sehr bemüht, bessere Ergebnisse zu erzielen, und in den wirklich einfachen Fällen gelingt dies beinahe ein bisschen, manchmal sogar einmal.
j) Kein Vorteil. JavaScript ist nicht einmal etwas Besonderes im Vergleich zu anderen dynamisch getippten Sprachen. Es ist überhaupt nicht in der Lage, irgendetwas Interessantes zu tun, was nicht auch von Lua, Python, Ruby usw. gemacht werden kann. Keine der JS-Implementierungen ist schneller als LuaJIT oder PyPy oder verschiedene andere fortgeschrittene JIT-Implementierungen anderer dynamischer Sprachen. JS hat im Vergleich zu anderen gängigen Sprachen keine Vorteile. Oh, außer es läuft nativ in einem Webbrowser ohne Plugin. Welches ist der einzige Grund auf der Welt, warum es so beliebt ist. Tatsächlich ist es der einzige Grund, warum es ein Ereignis gibt. Wenn jemand vor 10 Jahren gedacht hätte: "Zum Teufel, lassen Sie uns eine vorhandene, gut gestaltete und etablierte Sprache in unseren Browser ziehen und die anderen Jungs dazu bringen, dasselbe zu tun, anstatt dass jeder diesen albernen kleinen Hackjob benutzt, den NetScape erfunden hat "Das Web würde heute viel anders (besser) aussehen. Stellen Sie sich die Zukunft vor, wenn Chrome Python als unterstützte Sprache in Chrome ablegt. Oder stellen Sie sich Folgendes vor: Google legt C / C ++ in Chrome als unterstützte Sprache ab (http://code.google.com/p/nativeclient/).