Technology Scout

JavaScript-Universum: eine Reise durch 20 Jahre JS-Geschichte
Kommentare

Werden alte Brötchen, aufgebacken mit „Punkt JavaScript“, wirklich wieder wie neu? Warum wir aktuell die Renaissance einer zwanzig Jahre alten Technologie mit dem Namen Mocha erleben.

Denken Sie sich einfach irgendein Wort aus – gerne auch mit einer organischen Bedeutung –, hängen Sie einfach mal .js an und schon haben Sie es geschafft. Zumindest finden Sie sich in Gesellschaft der abertausenden Erschaffer von sinnvollen und weniger sinnvollen JavaScript-Frameworks. Ich persönlich habe sogar oft das Gefühl, dass man bei der aktuellen JavaScript-Euphorie eines komplett vergessen hat – die Funktionalität. Das entstandene „Nichts“ wird dann aber noch „Performance-de-optimiert“. Keine Ahnung was es tut, aber es gibt tatsächlich ein Projekt mit dem Namen „Nothing“. Und klar braucht die Welt keine dreißig verschiedenen JavaScript-Bibliotheken zum Parsen von Commandline-Parametern, aber JavaScript lebt halt in einer eigenen anarchischen Welt. Egal, welcher Statistik man folgt, man wird JavaScript immer ganz vorne finden, oft sogar mit weiterem Abstand auf der Pole-Position. Und obwohl eigentlich eine Marke der Firma Sun bzw. Oracle, entwickelt sich die Sprache so rasant wie unkontrolliert – wobei sie sich kaum mehr ändert, sondern eher immer tiefer in fast alle Bereiche der Softwareentwicklung eindringt.
Werfen wir zunächst einen Blick zurück zu den Anfängen: in den Spätfrühling des Jahres 1995. Es war einmal ein kleines Start-up mit Namen „Netscape“, und für den Browser „Navigator“ wurde eine Programmiersprache gesucht. Den Job bekam der Entwickler Brendan Eich, der dann – angeblich in zehn Tagen – einen ersten Entwurf einer neuen Sprache erstellte. Damals hieß das noch Mocha, später dann LiveScript. Der finale Name JavaScript wurde nach einer Kooperation mit Sun (Erfinder von Java) festgelegt. Technisch haben die beiden Sprachen (Java und JavaScript) aber nur wenig Ähnlichkeiten; einmal abgesehen davon, dass man sich damals wohl im Kaffeehype befunden haben muss, bei all den Mokkas, Java-Mischungen und Bohnenvarianten. Eich selbst ist heute der CTO der Mozilla Foundation.
Die neue Sprache sollte einen ähnlichen Effekt wie das Entwicklungssystem Hypercard von Apple haben. Mit Hypercard konnten auch Nichtentwickler erstmals interaktiv Anwendungen zusammenklicken. Das zugehörende HyperTalk-Skript war eine der „natürlichsprachigen“ Programmiersprachen, die dann später die Basis für AppleScript oder auch Flash bildeten – damals wirklich revolutionär und sicherlich die Basis für eine Menge später erfolgreicher Systeme. JavaScript (oder Mocha) nutzt syntaktisch eine Reihe von Grundkonzepten aus C/C++, daneben aber auch Elemente aus „Scheme“ (Closures/Lambda) sowie das Konzept der protypischen Objekterzeugung aus „Self“.
Die Eignung für Anfänger scheint ja durchaus gelungen zu sein, manche bezeichnen JavaScript auch als die Sprache, die genutzt werden kann, ohne sie jemals zu erlernen. Solange es sich um Miniskripte wie etwa bei Formularen handelt, vielleicht noch akzeptabel, bei systemkritischen Anwendungen aber eventuell gar fatal.
Obwohl zunächst als Browser-Skriptsprache entstanden, überschlugen sich damals ja die technologischen Meilensteine. Nach einer kurzen Euphorie bei rein statischen Webseiten, entwickelten sich auch dynamische Serveranwendungen rasant. Was kaum jemand weiß, ist, dass auch JavaScript – oder wie immer der Name zu diesem Zeitpunkt gerade war – schon früh einen ersten Auftritt als serverseitge Skriptsprache hatte. Zunächst aber nur, um sofort hinter Java, PHP aber auch Tcl oder VBScript zurückzutreten. Verständlich, dass eine Sprache mit maximalem Time-to-Market-Fokus und in einem reinen Interpreter-Modus keine Wettrennen gewinnen konnte. Aber zumindest für kurze Zeit gab es die Unterstützung für JavaScript in den damaligen Netscape-Webservern.

Node.js – JavaScript auf dem Server

Der Weg zu Node.js war eigentlich vorbestimmt. Bis dato waren die Bereiche Frontend und Backend zumindest technologisch und oft auch personell voneinander getrennt. Die Domäne von JavaScript war eben die Frontend-Seite und damit der Browser. Mit Node.js wird JavaScript auch zur Sprache für die Entwicklung im Backend. Wirklich neu ist das Ganze nicht, wie wir bereits sahen – schon der Netscape-Webserver konnte dynamische Seiten mit JavaScript erstellen. Interessant sind aber die internen Details der Nutzung von JavaScript.
Bei der Konstruktion der Sprache hat Eich auf Konzepte wie Multitasking verzichtet – nix für Rookies halt. Bei Node.js bildet die JavaScript-Engine das Herz, allerdings ohne Multitasking einzuführen. Vielmehr stützt man sich auf libevent ab. Interessant, da es weder Prozesswechsel noch typische Probleme von Nebenläufigkeit oder Parallelität gibt. Alle Anfragen werden in einem einzigen Thread verarbeitet, sozusagen ein kleines Stückchen hier und ein Stückchen da. Damit es trotzdem eine gewisse Form der sequenziellen Parallelität gibt, muss der Entwickler ran. Ein Programm in Node.js ist immer eine Kette von Callbacks. Anstatt auf die Rückkehr etwa einer Datenbankabfrage zu warten, wird ein Callback installiert und der Thread räumt einer Parallelanfrage ein wenig Rechenzeit ein. Liegen Daten aus der Datenbankabfrage vor, reiht sich der entsprechende Callback in die Warteschlange ein und wartet darauf, dass eine andere Anfrage einen Callback installiert hat, um danach selbst den Stab weiterzureichen und so fort. Dies ist aber Konvention und kein Zwang. Eine fehlerhafte Schleife und die Gesamtperformance kann massiv beeinflusst werden. Vermutlich einer der Gründe, warum sich Node.js noch kaum bei Hostern findet.
Letztlich kann Node.js aber überall dort eingesetzt werden, wo sich auch andere serverseitige Webtechnologien finden lassen. Normalerweise wird aber kein Webserver benötigt; ein HTTP-Server lässt sich mit ein paar Codezeilen in Node.js selbst implementieren. Die Domäne von Node.js liegt dabei eher bei Aufgaben, bei denen viele Clients regelmäßig mit kleinen Datenpaketen versorgt werden sollen. Und hier nutzt man dann vielleicht WebSockets oder HTTP lediglich zum Verbindungsaufbau und stellt mit Node.js ein Backend etwa für eine AJAX-/Web-2.0-Anwendung zur Verfügung. Für solche Aufgaben existieren dann Ansätze (etwa wie meteor.com), die dann die Grenzen zwischen Backend und Frontend verschwimmen lassen. Dabei kann dann ein Codestück dynamisch die ausführende JavaScript-Engine wechseln – die Anwendung wird dabei mithilfe von Ideen aus der Peer-2-Peer-Welt auf Browser und Server verteilt.
Die Anwesenheit von Node.js stellt dann aber auch einfach nur eine Runtime für JavaScript-Anwendungen bereit. Hier finden sich mittlerweile etliche Tools und Utilities; etwa das Build-Tool „Grunt“ oder Compiler wie „CoffeeScript“ und nicht zuletzt auch den Node Package Manager (npm).
Bemerkenswert und vielleicht auch eher weniger förderlich ist die enorme Menge an unterschiedlichen Frameworks, welche die Node.js-Umgebung zur Plattform für die Anwendungsentwicklung erweitern. Dazu gehören sicherlich so populäre Vertreter wie Express und Backbone, aber auch ein unüberschaubare Menge an Model-View-Controller-Frameworks, Template-Engines und Bindungen an die diversen Datenbanken.

JavaScript-Engines – Planet der Affen

Mozilla’s JavaScript-Engine heißt SpiderMonkey – und man hat sich früh dazu entschieden, die Engine vollständig Standalone, d. h. ohne Browser, HTML und HTTP zur Verfügung zu stellen. Zunächst war wohl eher die Nutzung als Scripting Engine für eigene Entwicklungen wie den Mail-Client geplant. Aber auch außerhalb der Mozilla Foundation wurde die Engine schnell zum Bestandteil von größeren Systemen wie etwa MongoDB.
Aus dem Chrome-Projekt heraus hat auch Google eine eigene JavaScript-Engine mit dem Namen V8 im Angebot. Nochmal rasanter hat V8 vielfach die SpiderMonkey-Integrationen verdrängt; auch Node.js etwa setzt auf V8. Aktuell ist eigentlich bei Mozilla IonMoney, eine weitere Compilerschicht, die einen weiteren zusätzlichen Performanceschub bringt.
Deutlich älter ist Rhino. Die in Java geschriebene JavaScript-Engine ist zwar eher träge, lässt sich aber mit wenigen Zeilen Code integrieren. Ebenso einfach lassen sich Java-Objekte in das DOM einblenden. In der Windows-Welt und hier unter .NET bietet Microsoft mit JScript eine dotnet-Sprache, die wir vielleicht als JavaScript-Dialekt bezeichnen können.

Back to the Roots – JavaScript Assembler

Für den nächsten Boost der maximalen JavaScript-Performance wählten die Ingenieure bei Mozilla einen sehr interessanten Ansatz: Der Weg führt quasi über eine Form von JavaScript Assembler mit dem Namen asm.js. Die Idee dabei ist die Nutzung eines reduzierten Subsets der Sprache und Vermeidung komplexer und aufwendiger syntaktischer Konstrukte. Hierbei entsteht faktisch JavaScript, das in jeder Engine lauffähig ist; auch wenn das deutlich unkomfortabler für einen Entwickler ist. Die Mozilla-eigene Engine (OdinMoney) kann nun aber den Code in einem hochoptimierten Modus ausführen. Dazu kommen nun 3rd-Party-Hersteller, die die neu entstandene Ablaufumgebung für die Ausführung ihres Zwischencodes nutzen. So bietet etwa die Firma Emscripten einen Compiler, der C-Code (eigentlich das Kompilat LVVM) nach asm.js übersetzen kann. Eine höchst beeindruckende Demonstration der Möglichkeiten zeigt die Portierung der Unreal-Spiele-Engine nach JavaScript. Auch wenn die wesentliche Power sicherlich aus der unterstützten Grafikhardware kommt, liegt das Potenzial natürlich auch in der Wiederverwertung von bestehendem C-Quellcode oder der Nutzung von bestehenden Entwicklungsumgebungen.

JSON – Objekt Prosa

JavaScript kennt eigentlich nur zwei Datentypen: Zahlen und Texte. Aus diesen beiden lassen sich nun Objektdaten oder Listen in Form von Arrays konstruieren. Die JavaScript Object Notation (JSON) definiert eine einfache Vorschrift für die Darstellung von Objektdaten in einem String. Zunächst gilt die Regel, dass ein Doppelpunkt den Attributnamen vom entsprechenden Wert trennt. Dazu lassen sich dann Listen von Attributen durch die Trennung mit einem Komma bilden. Schließlich dienen geschweifte Klammern der Markierung von Objekten, eckige Klammern markieren Arrays. Letztlich entsteht damit ein textuelles Serialisierungsformat, das für den Datenaustausch genutzt werden kann. Dabei hat JSON mittlerweile das XML-X in AJAX um Längen geschlagen; faktisch ist JSON zum Standardformat aufgestiegen. Hier kommt leider wieder eine Grundströmung in der JavaScript-Welt zum tragen: oft sind die Dinge einfach simpel, aber eben oft auch zu simpel. So fehlt JSON etwa jegliche Form einer Schematisierung. Ebenso wenig lassen sich damit beispielsweise Validierungen ableiten.
Eigentlich kommt hier ein weiterer Datentyp hinzu: die Funktion. Tatsächlich werden in JavaScript auch Funktionen in Variablen gespeichert. Und ein JavaScript-Objekt ist faktisch nichts als ein Array, wobei die Schlüsselnamen auf Attributwerte verweisen. Und ein solcher Wert kann auch eine Funktion sein, womit wir zur Definition von Methoden kommen.
JavaScript ist vollständig dynamisch und eine Festlegung der Variablentypen existiert nicht. Damit kann eine Variable durchaus ihren Typ ändern. Ist diese zunächst „undefined“, kann die Variable die Rolle einer Funktion, eines Texts, einer Zahl usw. annehmen. Und oft ist der Rollenwechsel dem Entwickler kaum bewusst. Insbesondere beim Aufbau einer Entwicklungsumgebung führt diese Dynamik zu Schwierigkeiten. Eine IDE kann nur schwer entscheiden, welcher Datentyp gemeint ist und ob es sich um die bewusste Einführung eines neuen Namens handelt oder einen Tippfehler. Und entsprechend mager sind die Möglichkeiten in Form von Hilfestellungen an den Entwickler. Ein Lösungsweg ist die Anreicherung des Quellcodes mit Metainformationen, etwa Doc-Kommentaren – damit kann die IDE Codevervollständigung anbieten und evtl. auch Hilfeinformationen kontextsensitiv einblenden. Leider ist hier aber kein echter Standard vorhanden, womit die IDE speziell auf etwa die typischen Vertreter von JavaScript-Frameworks angepasst werden muss. Die Alternative ist die ständige Analyse des Quelltexts und die Ableitung von strukturellen Informationen. Nutze ich als Entwickler etwa einen bestimmten Schlüssel als Array-Index, dann wird mir dieser hiernach an Stellen angeboten, bei denen ich sonst den Namen erneut eingeben müsste. Doch auch hier kann die IDE nicht zwischen gewollten Änderungen und ungewollten Vertippern unterscheiden.
Auch wirft die Beschränkung auf die wenigen Datentypen Probleme beim Transport von binären Daten wie Bildern oder Videos auf. Für die Lösung des Problems mit binären Daten hat sich BSON entwickelt – quasi eine Erweiterung von JSON um binäre und andere Datentypen. Auch für die Schematisierung, die wir auch etwa zur Beschreibung von Web Services benötigen, haben sich einige Initiativen herausgebildet. Nur ein übergreifender Standard entwickelte sich bisher nicht, dazu fehlt hier der Prozess oder eine Community.
Ganz im Sinne des Dogfooding entsteht gerade mit „Orion Node“ eine IDE für JavaScript, die selbst in JavaScript geschrieben in Node.js auf dem Server und natürlich im Browser arbeitet. Das Mutterprojekt ist hier Eclipse Orion. Dieses System soll (in Zukunft) einmal alle Möglichkeiten von Eclipse, aber eben als Browseranwendung, beinhalten. Dabei sollen final auch alle Plug-ins für die Desktop-Eclipse-Version ebenfalls in Orion nutzbar sein. In dem Zusammenhang taucht immer wieder die Forderung auf, Eclipse-Plug-ins auch in anderen Sprachen (als Java) entwickeln zu können; und dabei steht JavaScript ganz vorne auf der Liste.

NoSQL und JavaScript – das ist der Perfect-Fit

Werfen wir einen Blick in Richtung der Datenbanken. Insbesondere die dokumentenorientierten NoSQL-Datenbanken wie MongoDB oder CouchDB legen einen großen Wert auf das schemalose Arbeiten mit Daten. Insofern ergibt es Sinn, auch eine Nähe zu JSON zu suchen und sich damit als Kandidat für die Persistenz in JavaScript-basierten Anwendungen anzubieten.
Durch die Einbindung einer JavaScript-Engine wird damit auch die Skriptsprache für die Erstellung von MapReduce-Jobs gesetzt. Teilweise wird die Engine dann auch für die Verarbeitung von Queries oder zur Konfiguration genutzt.
Um es kurz und auf den Punkt zu bringen: NoSQL mit der Speicherung von JSON ist der Perfect-Fit, wenn JavaScript die Entwicklungssprache ist.

JS-Frameworks

Insbesondere auf der Browserseite haben sich schnell eine Reihe von JavaScript-Bibliotheken verbreitet. Zunächst war hier die wesentliche Aufgabe, ein einheitliches und vor allem browserübergreifendes Fundament für Entwicklungen zu legen. Gerade deshalb gehören die Zugriffsfunktionen auf das HTML-Dokument zu den Basisfunktionalitäten. Dazu kamen und kommen diverse Manipulationsmöglichkeiten des CSS-Models.
Damit kommen wir dann zu altbekannten Namen wie Prototype, JQuery und script.aculo.us. Deren Funktionalitäten stellen Spracherweiterungen, AJAX-Kommunikation aber auch viele visuelle Widgets für die Benutzeroberfläche zur Verfügung. Insbesondere hier ist die Liste der nicht genannten Systeme sicherlich noch mehrere tausend Einträge lang.
Hier ist mit Sencha’s Ext JS eines der größeren kommerziellen Systeme beheimatet. Neben der Bereitstellung des Frameworks in unterschiedlichen Flavours konzentriert man sich hier auch auf das Tooling – meiner Ansicht nach ein sehr erfolgversprechender Weg.

JS als Compiler-Ziel

Wenn Sie ernsthaft beginnen, mit JavaScript größere Systeme zu entwickeln, werden die konzeptionellen Eigenarten zu echten Problemen. In der Regel wird man zunächst versuchen, mit einem Framework fehlende objektorientierte Eigenschaften nachzubilden. Hier findet man sich dann schnell in einer Position, in der man als Entwickler faktisch JSON-Code schreibt. Das Tooling hier ist oft nur mit viel Mühe akzeptabel in Gang zu bringen. Oft ist das Ergebnis nicht viel mehr als Syntax-Highlighting, im Bereich Auto-Completion oder gar Refactoring finden sich höchstens Spuren.
Interessant ist hier die Nutzung etwa von Cross-Compilern. So ermöglicht etwa GWT (Google Web Toolkit) die Entwicklung vollständig in Java. Ein Compiler übernimmt dann die Übersetzung nach JavaScript für die Anteile der Anwendung, die später im Browser laufen sollen. Hierbei stützt sich GWT faktisch auf die hier implementierten HTML-Widgets für die Oberflächengestaltung. Ähnliche Aufbauten wären letztlich auch für andere UI-Bibliotheken aber auch für andere Wirtssprachen denkbar. Der große Vorteil solcher Systeme ist, dass man all die hübschen Fähigkeiten der Wirtsprache mitnehmen kann; im Fall von Java angefangen bei Maven und Co. für das Build-Management, über Codegeneratoren aus UML, bis zu den Refaktorings und Eingabehilfen von IDEs wie Eclipse oder IntelliJ.
Neben den Cross-Compilern existieren aber auch Sprachen, die man vielleicht am ehesten mit einem Pre-Processor vergleichen könnte. Ähnlich wie damals C++ zunächst nur einen Pre-Processor zu C darstellte, arbeitet CoffeeScript in Bezug auf JavaScript. CoffeeScript stellt eine Reihe von Syntaxelementen zur Verfügung, wie etwa „Class“, und vereinfacht teilweise radikal. Am Ende wird aus CoffeeScript dann wieder JavaScript. Nachteil ist heute noch, dass ein Debugging im übersetzten JavaScript erfolgt und sich damit nur mit viel Erfahrung die Verbindung zum Ursprungs-Sourcecode herstellen lässt.

Derivate und Nachfolger?

Mittlerweile und mit Erscheinen dieses Artikels ist JavaScript gerade volljährig geworden. Aber auch nach all den Jahren halten sich die Innovationen in Grenzen. Wahrscheinlich läuft das Gros des vorhandenen Codes auch noch auf Browsern, die im Jahr 2000 erschienen sind. Ein Signal hier ist etwa die Aussage der jQuery-Macher, mit der Version 2.0 nur noch den Internet Explorer ab der Version 9 und höher zu unterstützen. Der Kahlschlag bringt mehr Performance und einen deutlich schlankeren Code.
Google versucht mit Dart einen Nachfolger für eine Skriptsprache im Browser zu etablieren. Eigentlich bringt Dart alles, was man sich wünscht; eine JavaScript-ähnliche aber doch aufgeräumtere Syntax, ein Set von durchdachten Bibliotheken und eine eigene (auf Eclipse basierende) IDE. Unterstützt ein Browser Dart nicht direkt– und nativ gibt es hier nur Google Chrome – kann Dart auch nach JavaScript kompilieren.
Einen ähnlichen Vorstoß versucht Microsoft mit TypeScript. Hier hält man sich zumindest in etwa an die Vorgabe der nächsten JavaScript-Version (ECMAScript 6). Auf die eigene Ausführumgebung verzichtet man, TypeScript kompiliert ähnlich wie CoffeeScript in eine allgemein verfügbare JavaScript-Variante und ist damit dann abwärtskompatibel.

Firefox OS – Ein Telefon aus JavaScript pur

Anfang des Jahres hat die Mozilla Foundation mit Firefox OS auf dem Mobile World Congress ein Betriebssystem auf der Basis des Firefox-Browsers vorgestellt. Ab Anfang Juli ist nun das erste Gerät in Spanien verfügbar; zu einem sicherlich subventionierten Kampfpreis von ca. 70 Euro (inkl. 30 Euro Startguthaben).
In den Anfängen hieß das Ganze einmal B2G für „Boot to Gecko“, und letztlich basiert das System im Wesentlichen aus einem Browser auf einem Smartphone. Alle Programme oder Apps sind dabei nichts anderes als Webanwendungen basierend auf HTML5, CSS und JavaScript. Dabei werden diverse Hardwareevents in Form von DOM-JavaScript-Events an eine JavaScript-Anwendung weitergegeben. Für die Nutzung etwa der Kamera stellt das OS dann sog. Activities zur Verfügung.
Das Ganze ist höchst genügsam in Bezug auf die notwendige Hardware – entsprechend günstig können die Geräte angeboten werden. Offiziell platziert sich Mozilla bewusst auf Zielmärkten im Bereich der Emerging Countries. Die großen Telekommunikationsunternehmen stehen Schlange, bietet sich doch bei Erfolg ein Weg aus den Zwängen und den Provisionsansprüchen von Apple, Google und Co.
Ironischerweise war für iPhone OS zunächst auch kein SDK mit Zugriff auf die native Umgebung geplant. Ursprünglich war wohl genau der Firefox-OS-Weg derjenige, der von Steve Jobs präferiert worden war. Aber natürlich lassen sich Links auf mobile Websites nur schwerlich in einem App Store „verkaufen“.
Aber die Bereitstellung einer Ablaufumgebung für JavaScript-Code mit Zugriff auf die Hardware ist ja eigentlich durchaus interessant. Und tatsächlich hat Apple genau dies bereits in der Schublade liegen; weitgehend unbekannt liegt hier mit iAd (dem Apple-Werbenetzwerk) ein Großteil der Funktionalitäten in Form von Bibliotheken aber auch von Entwicklertools bereits vor.

Ausblick

Das in den letzten fast zwanzig Jahren entstandene Universum um JavaScript herum lässt sich nur schwer bewerten. Auf der einen Seite hat es JavaScript mit seinen syntaktischen Möglichkeiten nie aus den Kinderschuhen herausgeschafft, auf der anderen Seite etabliert sich JavaScript in vielen professionellen Bereichen wie der Entwicklung im Backend oder als Basissprache auf mobilen Geräten.
Insbesondere im Bereich der professionellen Entwicklung entsteht ein hoher Bedarf an Tools für die Entwicklung von komplexen Systemen aber auch im Bereich der Dokumentation oder für den Softwaretest. Mit einem vermehrten Einsatz von JavaScript werden sicherlich auch die entsprechenden Entwicklungsumgebungen nicht mehr lange auf sich warten lassen.
Und damit möchte ich mich empfehlen bis zur nächsten Ausgabe des Entwickler Magazins.

 

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -