Zeigt die Tatsache, dass anonyme selbstreferenzierende Funktionsabschlüsse in JavaScript so häufig vorkommen, dass JavaScript eine unvollständige Spezifikation ist? Wir sehen so viel davon:
(function () { /* do cool stuff */ })();
und ich nehme an, alles ist Geschmackssache, aber sieht das nicht wie ein Kludge aus, wenn Sie nur einen privaten Namespace wollen? Konnte JavaScript keine Pakete und richtigen Klassen implementieren?
Vergleichen Sie mit ActionScript 3, das ebenfalls auf ECMAScript basiert
package com.tomauger {
import bar;
class Foo {
public function Foo(){
// etc...
}
public function show(){
// show stuff
}
public function hide(){
// hide stuff
}
// etc...
}
}
Im Gegensatz zu den Konvolutionen, die wir in JavaScript ausführen (aus der jQuery-Plugin-Authoring-Dokumentation ):
(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 );
Ich bin mir bewusst, dass diese Frage leicht zu einem Rant über Vorlieben und Programmierstile ausarten kann, aber ich bin tatsächlich sehr gespannt, wie Sie als erfahrene Programmierer diesbezüglich denken und ob es sich natürlich anfühlt, verschiedene Eigenheiten einer neuen Sprache zu lernen, oder kludgy , wie eine Problemumgehung für einige grundlegende Programmiersprachenkomponenten, die einfach nicht implementiert sind?
quelle
Antworten:
Die meisten Kommentare sprechen gegen den Mythos, dass "Prototypen Klassen für arme Männer sind", und ich wiederhole nur, dass prototypbasierte OO in keiner Weise klassenbasierten OO unterlegen sind.
Der andere Punkt "ein Kludge, wenn alles, was Sie wollen, einen privaten Namespace". Es könnte Sie überraschen, dass Scheme genau dasselbe Kludge verwendet, um Bereiche zu definieren. Das hat nicht aufgehört, das archetypische Beispiel für lexikalisches Scoping zu werden.
Natürlich ist der 'Kludge' im Schema hinter Makros versteckt ....
quelle
Zunächst ein paar Dinge:
Eine andere Sichtweise auf JavaScript sind die 1 Million und 1 Dinge, die Sie mit der Funktion als Konstrukt tun können. Es ist alles da, wenn Sie danach suchen. Es ist einfach nie weit von einer Funktion entfernt.
Das jQuery-Plug-in-Authoring-Ding ist schrecklich. Ich habe keine Ahnung, warum sie das befürworten. $ -Erweiterungen sollten allgemein verwendbare Dinge sein, die $ bereits ziemlich gut behandelt hat und keine Build-me-a-complete-Widget-Methoden. Es ist ein DOM-API-Normalisierungstool. Die Verwendung ist am besten in Ihren eigenen Objekten begraben. Ich sehe den Reiz, es als vollwertiges UI-Bibliotheks-Repository zu verwenden, nicht.
Pakete im clientseitigen Web sind sinnlos
Was ich persönlich an Paketen im clientseitigen Web nicht mag, ist, dass wir im Grunde so tun, als würden wir etwas tun, was wir wirklich nicht tun. In einem Post-.NET-Webformular und einem schrecklichen Zeug, das niemals aus unserer Java-Freundewelt herausgekommen ist, stelle ich mir lieber ein Stück HTML mit verknüpften Ressourcen als das vor, was es wirklich ist und versuchen Sie nicht, lernresistente OS-App-Entwickler zu beschwichtigen, indem Sie so tun, als wäre es etwas anderes. In JS auf der Client-Seite wird nichts "importiert", es sei denn, Ajax macht etwas Schreckliches, das Browser-Caching nicht kennt, was ja viele versucht haben. Für den Browser ist nur wichtig, dass er entweder geladen und interpretiert wurde oder nicht. Auf dem Client ist kein Code mehr gespeichert, der "nur für den Fall" verwendet werden kann. aus guten gründen. Das erste Problem ist, dass ich gerade die Plug-In- und Browser-Plug-In-Abhängigkeiten für Web-Apps als Phänomen beschrieben habe, das im Allgemeinen nicht gut funktioniert hat. Wir wollen jetzt Web. Nicht nach dem dritten Update von Adobe oder Sun in dieser Woche.
Die Sprache hat, was sie für die Struktur braucht
JS-Objekte sind in hohem Maße veränderbar. Wir können verzweigte Bäume von Namespaces haben, zu jedem Grad, den wir für nützlich halten und es ist sehr einfach zu tun. Aber ja, für alles, was wiederverwendbar ist, muss man die Wurzel einer Bibliothek im globalen Raum stecken. Alle Abhängigkeiten werden ohnehin gleichzeitig verknüpft und geladen. Wozu also sonst noch etwas tun? Der Punkt, den globalen Namespace zu vermeiden, ist nicht, dass irgendetwas dort schlecht ist. Es ist zu viel Zeug, weil Sie das Risiko von Namespace-Kollisionen oder versehentlichem Überschreiben von Kernsprachen-Features eingehen.
Nur weil es beliebt ist, heißt das noch lange nicht, dass wir es richtig machen
Wenn Sie dies nun in einer clientseitigen Web-App sehen:
Das Problem ist nicht, dass uns Tools fehlen, um eine App zu strukturieren. Das Problem ist, dass die Leute die Struktur nicht schätzen. Für 2-3-seitige einmalige temporäre Wegwerfstellen bei einer Designagentur habe ich damit kein wirkliches Problem. Hässlich wird es, wenn Sie etwas Wartbares und Lesbares bauen müssen, das sich leicht modifizieren lässt.
Wenn Sie jedoch an den Ort gelangen, an dem es Zeit ist, alle wiederverwendbaren Objekte und Fabriken zu implementieren, und sich möglicherweise ein oder zwei neue temporäre Vars in diesen Prozess einschleichen, ist dies eine Annehmlichkeit.
Es gibt jedoch Implementierungen von JS mit Paketen / Modulen
Denken Sie daran, dass in Node.js, wo solche Dinge viel sinnvoller sind, Module vorhanden sind. JS ist das einzige, was in der Gleichung steht, vorausgesetzt, wir können die Uber-Config-Hölle vermeiden, die andere Sprachen plagt, und jede ausgeführte Datei hat ihren eigenen isolierten Gültigkeitsbereich. Auf einer Webseite ist das Verknüpfen einer js-Datei selbst die import-Anweisung. Schnelleres Importieren ist nur eine Verschwendung von Zeit und Ressourcen, da das Abrufen der Ressourcen viel mehr Aufwand erfordert als das Hinzufügen von Links zu Dateien, wenn Sie wissen, dass sie in einem Browser zwischengespeichert werden, wenn eine andere Seite sie erneut benötigt. Versuchen Sie also, den globalen Raum aufzuteilen, indem Sie etwas anderes tun, als Adapterobjektfactorys wie jQuery oder traditionellere Objekte zu erstellen, die eine große Teilmenge von Aufgaben in einer bestimmten Domäne abdecken und gleichzeitig einen Platz in der globalen Datenbank einnehmen. Dort'http://wiki.ecmascript.org/doku.php?id=harmony:modules
Nein, es ist nichts falsch an Auto-Invokern, die verwendet werden, um globale Namespace-Verschmutzung zu vermeiden, wenn es einen guten Grund gibt, solche Dinge zu verwenden (meistens gibt es keinen). Und wir haben persistente privat äquivalente Eigenschaften in unseren Objekten (definieren Sie einfach eine Variable im Konstruktor und machen Sie sie nicht als Eigenschaft verfügbar).
Die Tatsache, dass wir solche Dinge tun KÖNNEN, ist jedoch fantastisch. Starke Auslastung ist ein Zeichen dafür, dass JS-Entwickler vielleicht noch reifen, aber es ist kein Loch in der Sprache für jeden, der nicht versucht, ein Paradigma in das clientseitige Web zu zwingen, das hier einfach keinen Sinn ergibt.
quelle
Das andere, was Sie vermissen, ist, dass javscript abwärtskompatibel sein muss. Wenn Sie versuchen, die Paketsyntax einzuführen, kann dies das Web auf verrückte Weise zerstören. Das wäre schlimm! Doug Crockford hat an verschiedenen Stellen darüber gesprochen und warum die Versuche, es hinzuzufügen, fehlgeschlagen sind.
quelle
Ja, es ist ein Kludge.
Viele Leute sagen, dass "Prototypen den Klassen nicht unterlegen sind". Ich bin anderer Meinung, aber das ist eine Frage der Präferenz. Aber das ist noch nicht einmal das eigentliche Problem mit JavaScript - das Problem ist, dass es ursprünglich als schnelle und schmutzige Skriptsprache für animierte Schaltflächen entwickelt wurde. Mitte der 90er hätte niemand gedacht, dass JavaScript dazu aufgefordert werden würde, einige der verrückten Dinge zu tun, die es derzeit macht.
quelle
Anonyme selbstaufrufende Funktionen ähneln eher Modulen als Klassen. Es ist ärgerlich, dass JavaScript standardmäßig im globalen Bereich ausgeführt wird. Das Komitee, das an JS.next arbeitet, erwägt ernsthaft, Module hinzuzufügen, damit Sie Ihre lokalen Variablen nicht in den globalen Bereich verschieben. Zum Glück haben die Funktionen von Javascript eine so praktische Semantik, dass wir eine anonyme Funktion relativ einfach als privaten Bereich verwenden können.
Ich verstehe überhaupt nicht, wie Klassen wirklich in die Diskussion eintreten, außer dass sie in vielen Sprachen das Top-Level-Scoping-Konstrukt sind. Ein besseres Modul / Paket / bitte-gib-mir-einen-lokalen-Gültigkeitsbereich-damit-ich-meine-Variablen-in-der-globalen-Umgebung-nicht-lasse-Konstrukt wäre sehr schön zu haben.
quelle
Vielleicht möchten Sie einen Blick auf ExtJS 3 und 4 werfen, wo es ihnen gelungen ist, Namespaces recht gut zu implementieren.
- hinzugefügt nach -1
Mein Punkt hier war, es ist möglich, all diese 'Windungen' zu verbergen und trotzdem einen ziemlich benutzerfreundlichen Code wie diesen zu haben:
quelle