Weitere Fragen zu HTML5 und Co beantwortet

Veröffentlicht am 16. April 2012

In den letzten Wochen und Monaten habe ich wie gewohnt via E-Mail, Twitter, Formspring und andere Kanäle Fragen zu HTML5 gestellt bekommen und beantwortet. Da wie immer gilt, dass es keine dummen Fragen, aber sehr viel öffentliches Interesse gibt, präsentiere ich hiermit einen weitereren Teil der allseits beliebten Serie „Fragen zu HTML5 und Co“ mit den neuesten Fragen und Antworten rund um unser liebstes Hype-Thema und den diversen dazugehörigen Webtechnologien.

Section-Elemente in Header-Elementen?

Ein Section-Element kann ja ein Header- oder ein Footer-Element beinhalten. Geht es aber auch anders herum? Im konkreten Fall geht es um ein Header-Element mit einem Warenkorb- und Kundenbewertungsbereich. Wäre es semantisch korrekt dafür ein Section-Element zu verwenden?

Erlaubt es eine solche Konstruktion auf jeden Fall – ob sie auch semantisch korrekt ist, hängt vom betroffenen Inhalt ab, aber ich denke im genannten Fall passt es. Generell gilt: Header- und Footer-Elemente dürfen jedweden Flow-Content enthalten, der selbst kein Header- oder Footer-Element ist. Flow-Content umfasst dabei so ziemlich alles, was es für Content bestimmten HTML-Elementen so gibt.

Wie baut man große JavaScript-Apps?

Da ich viel mit Actionscript gearbeitet habe, habe ich immer noch nicht den Sprung zu JS gewagt, da ich immer noch das Gefühl habe, das JS mehr dieses Prototyping-Dingsda macht statt mit Klassen zu arbeiten. In AS und PHP zB. habe ich meine Klasse mit Constructor und den Methoden und Eigenschaften und kann das ganze schön in eine Datei packen und KlasseA nennen.

Wie sieht denn ein allgemeiner Workflow in JS aus? Ich sehe immer nur irgendwelche Codschnipsel, aber ich habe noch nicht wirklich begriffen, wie man komplexere Programme in JS wirklich umsetzen kann (z.B. nach MVC), also dass man die einzelnen Funktions- und Logikeinheiten sinnvoll organisiert.

Das „Prototyping-Dingsda“ in JS (prototypische Vererbung) ist eigentlich simpler und mächtiger als Veerbung via Klassen. Objekte erben direkt von anderen Objekten und die Zwischenkonstruktion „Klasse“ fällt einfach weg. Und das beste: Klassensysteme kann man via Prototypen implementieren. Wenn du also unbedingt möchtest, kannst du problemlos Klassen in JavaScript bekommen. Links:

Was App-Struktur angeht, kommt es drauf an, was du genau in JS machen möchtest. Serverseitige Umgebungen wie Node bieten z.B. ein Modulsystem. Ansonsten gibt es auch für den Browser viele fertige Lösungen aus der Dose. Diesen Artikel über RequireJS in Zusammenarbeit mit AMD (asynchronous module definition) würde ich mal exemplarisch durchlesen. Was MVCeske Konstruktionen angeht, gibt es auch mehrere Lösungen. Unter anderem diese hier sind empfehlenswert:

Für große Apps allgemein würde ich mir mal diese drei kurzen Talks reinziehen, die alle Themen rund um große JavaScript-Apps streifen.

Webcam-Chat mit HTML5?

Ich suche eine Möglichkeit, mit HTML5 Webcam-Chats zwischen bis zu vier Personen zu verwirklichen. Ich habe dabei die jQuery Webcam-API entdeckt, aber es erscheint mir, als ob es hier lediglich um die Möglichkeit geht die Webcam anzusprechen und es nicht möglich ist das Bild auch irgendwie an andere zu übertragen. Ist es nicht möglich, Webcam-Daten zu kopieren und vor allem an andere übertragen?

Was Webcam-Chats angeht, habe ich eine gute Nachricht und eine schlechte Nachricht. Die Gute ist, dass Webcam-Chat (inklusive Sound, d.h. Skype-klonen) tatsächlich bei den klugen Köpfen rund um HTML5 eine Rolle spielt. Es wird aktiv daran gearbeitet und das Ganze läuft unter dem Titel WebRTC. Die schlechte Nachricht ist, dass WebRTC noch eine in einer sehr frühen Phase steckt und noch nicht ernsthaft benutzbar ist – außer in Chrome-Nightlies läuft die API noch nirgendwo und ich möchte wetten, dass die ganze Technologie noch einige größere Änderungen vor sich hat. Da hilft, fürchte ich, erst mal nur Geduld.

Warum kein new Array() in JavaScript?

In diesem Artikel und dem besprochenen Buch heißt es Finger weg von new Array(). Wieso?

Neue Arrays macht man in JavaScript am einfachsten (weil am kürzesten) mit dem Literal []. Es gibt keinen Grund, sich mit new Array() einen Wolf zu tippen, denn das bringt gegenüber [] keine Vorteile. Im Gegenteil: new Array() macht, je nachdem wie viele Argumente man ihm mitgibt, sehr unterschiedliche und teils verwirrende Dinge:

var a = new Array(3);     // Leeres Array mit length = 3
var b = new Array(3, 14); // Array [3, 14]
var c = new Array(3.14);  // RangeError: Invalid array length

All den Stress hat man mit [] nicht – da kommt einfach ein Array mit genau den Elementen heraus, die man hineingesteckt hat.

Weitere Fragen?

Eure Fragen zu HTML5, JavaScript und anderen Webtechnologien beantworte ich gerne! Einfach eine E-Mail schreiben oder Formspring bemühen und ein bisschen Geduld haben – falls ich gerade unterwegs bin, kann es mit Antwort manchmal etwas dauern, doch früher oder später schreibe ich garantiert zurück.

Die Karte des HTML5-Universums

Veröffentlicht am 10. April 2012

Ich habe glaube ich noch keinen einzigen Talk über HTML5 gehalten, in dem ich nicht auf diese Karte des HTML5-Universums zurückgegriffen habe:

Die Karte des HTML5-Universums

Man kann unter Zuhilfenahme dieses Bildchens sehr anschaulich und vor allem zeiteffektiv ein paar wichtige Dinge über HTML5 erklären. Zum Beispiel sieht man sehr schön

  • das Verhältnis der beiden HTML5-Spezifikationen nebst den jeweiligen Web Developer Editions zueinander sowie zum Alltagsbegriff „HTML5“ (alles Teilmengen voneinander),
  • dass neben W3C (blaue Kreise) und WHATWG (grün) noch viele weitere Parteien das Web aufmischen (orange) und dass HTML5 nicht alles ist, was das Web Neues zu bieten hat,
  • den schieren Umfang des ganzen neuen Zeugs (jeder Kreis repräsentiert ein eigenes, unter Umständen sehr umfangreiches Spezifikationsdokument),
  • dass es richtig komplizierte Sonderfälle in diesem ganzen Web-Zirkus gibt (die eingestellte Web SQL Database, die aus einer API und einem Protokoll bestehenden Web Sockets),
  • und dass jQuery und Node.js wirklich nichts mit HTML5 zu tun haben und das auch bei CSS3 eine eher problematische Einordnung ist.

Da ich mindestens zwei mal pro Monat eine E-Mail bekomme, in der gefragt wird, wo man denn diese Grafik herkriegen kann und ob man sie in Slides/Büchern/Abschlussarbeiten verwenden darf, steht das gute Stück ab jetzt offiziell unter einer Creative Commons Namensnennung 3.0 Deutschland Lizenz und hat ein ein Github-Repository für Bugreports und Weiterentwicklung. Es gibt (mit Inkscape gebaute) SVGs sowie PNGs und jeweils eine Variante mit weißem und eine mit schwarzem Hintergrund. Macht damit was ihr wollt!

Termine für April und Mai 2012

Veröffentlicht am 4. April 2012

Im April und Mai 2012 gibt es für interessierte Webtechnologie-Padawane nur zwei (öffentliche) Möglichkeiten, sich vom Webtechnologie-Erklärbären mit frischem Wissen rund um die neueste Neuheiten in den Browsern dieser Welt ausrüsten zu lassen. Allerdings sind die beiden Termine ganz gut kombinierbar, da sie direkt nacheinander am gleichen Ort stattfinden:

  • 7. - 9. Mai 2012 in München: HTML5-Schulung bei der Open Source School. Mein drei­tä­gi­ges HTML5-Standardprogramm stattet die Teilnehmer im Druckbetankungsverfahren mit (so gut wie) allem aus, was man zu HTML5 wissen muss, von semantischem Markup bis hin zu Canvas-Frameworks. Die Themen sind im Einzelnen:
    • Hintergründe und Entstehungsgeschichte
    • Geolocation und Gerätesensorik
    • HTML5-Schnelleinstieg
    • Semantisches HTML5
    • HTML5-Formulare
    • Offline-Webanwendungen
    • Multimedia im Browser
    • Web Workers
    • Die File-API
    • Polyfills
    • Das Canvas-Element
    Geboten wird ein großer Praxisanteil, kleine Arbeitsgruppen und ein Buch gibt es obendrein.
  • 10. -11. Mai 2012 in München: CSS3-Schulung bei der Open Source School. Mein zweitä­gi­ges CSS3-Standardprogramm katapultiert die Teilnehmer in das CSS3-Zeitalter, in dem Webfonts und Farbverläufe fließen. Das gesamte Programm:
    • Hintergründe und Entstehungsgeschichte
    • CSS3-Selektoren
    • Farben und Farbverläufe
    • Boxen und Rahmen
    • CSS3-Layout
    • Transformationen
    • Transitionen und Animationen
    • Schrifteinbettung und -gestaltung
    • Media-Queries
    Ein großer Praxisanteil, kleine Arbeitsgruppen und ein Buch als Bonus gibt es auch hier.

ECMAScript 6: Block Scope und Konstanten

Veröffentlicht am 2. April 2012

Anders als im ECMAScript 5 rüstet ES6 nicht nur hier und da ein paar Funktionen nach, sondern bietet für viele Neuerungen neue Syntax und Konzepte, wobei einschränkend gesagt werden muss, dass viele der „Neuheiten“ so neu gar nicht sind. Das Meiste ist irgendwo geklaut: aus proprietären Browser-Erweiterungen, aus CoffeeScript, anderen Programmiersprachen oder gar aus dem gescheiterten ES4-Standard. In diese Kategorie der nicht ganz so neuen Neuheiten fallen auch die neuen blockgebundenen Variablen (let) und Konstanten (const), um die es in diesem Artikel geht. Die neuen Features funktionieren zur Zeit in allem, was auf neuere V8-Engines aufsetzt, also Chrome und Node, wobei es nicht mehr lange dauern dürfte, bis auch andere JS-Implementierungen nachrüsten. Wenn es endlich so weit ist, haben die JavaScript-Programmierer dieser Welt zwei Probleme mit Variablen weniger.

Zwei Probleme mit Variablen

Problem Nummer 1 ist, dass in ECMAScript 5 und älter der Geltungsbereich von Variablen die Funktion ist, in der sie deklariert wurden. Wenn man den folgenden Schnipsel ausführt …

function foobar(foo){
    if(foo){
        var bar = 42;
    }
};

… wird der Code interprtiert, als hätte man das folgende geschrieben:

function foobar(foo){
    var bar;
    if(foo){
        bar = 42;
    }
};

Dieses Verhalten bringt es mit sich, dass man, wenn man Variablen innerhalb von Blöcken deklariert, damit auch die Umwelt außerhalb der Blöcke verunreinigt:

function foobar(foo){
    if(foo){
        var bar = 42;
    }
    // "bar" ist hier auch noch 42
};

Das mag zwar in vielen Fällen wie dem obrigen nicht groß stören, in anderen hingegen schon:

var bar = { 'hallo': 1337 };

function foobar(foo){
    if(bar[foo]){
        return bar[foo];
    }
    else {
        var bar = 42 * 666;
        return bar;
    }
};

var x = foobar('hallo'); // Na, wer weiß was hier passiert?

Selbst wenn dieses Verhalten nicht oft zu Problemen führt, so ist es doch weder ist es sonderlich intuitiv, noch wird es wirklich gebraucht. Im Gegenzug ist es recht mühsam, in ECMAScript 5 und älter Variablen auf Blöcke zu beschränken, denn außer sofort ausgeführten Funktionen hilft hier nichts:

function foobar(foo){
    whatever();
    if(foo){
        (function(){
            var bar = 42;
        })();
    }
    // "bar" ist hier undefined
};

Das funktioniert zwar, ist aber der Code-Eleganz nicht besonders zuträglich und für alle mit eher mittlguten JavaScript-Kenntnissen unnötig verwirrend.

Das zweite Problem ist, dass es in ECMAScript 5 und älter eben nur Variablen und keine Konstanten gibt. Es existieren zwar Konventionen, gemäß derer man Variablen durch Allcaps-Namen als „Konstanten“ kennzeichnet, doch das allein hält im Zweifelsfall niemanden davon ab, die „Konstante“ zu überschreiben:

var KONSTANTE = 42;

KONSTANTE = 1337; // Funktioniert!

Die einzige in ES5 denkbare Lösung besteht darin, mittels Property Descriptor die gewünschte Konstante als nicht-überschreibbare Eigenschaft auf einem Objekt anzulegen:

Object.defineProperty(window, 'KONSTANTE', {
    writable: false,
    enumerable: true,
    configurable: false,
    value: 42
});

KONSTANTE = 1337; // TypeError: Cannot assign to read only property 'KONSTANTE'

Auch hier gilt: das funktioniert zwar, aber als ersthafte Lösung kann man dieses Konvolut wohl niemandem verkaufen. ECMAScript 6 schafft nun die Probleme rund um Konstranten und var aus der Welt, indem mit let und const zwei Alternativ-Formen von Variablen eingeführt werden.

Lösung 1: let statt var

Verwendet man zur Deklaration einer neuen Variable das Schlüsselwort let statt var, so erhält man eine an den Block gebundene Variable, die jenseits ihrer Schleife oder Kontrollstruktur nicht sichtbar ist. Damit bleiben zum Beispiel die Zähler einer For-Schleife ausschließlich innerhalb der Schleife gültig:

for(let i = 0; i < 4; i++){
}
console.log(i); // ReferenceError: i is not defined

Hierfür braucht es nicht zwingend echte Kontrollstrukturen oder Schleifen, auch bei leeren Blöcken funktioniert let:

{
    let i = 42;
}
console.log(i); // ReferenceError: i is not defined

Aus der Blockbindung folgt, dass let-Deklarationen nur in einem Block, in Funktionscode oder auf Programmebene vorkommen dürfen:

if(true) var i = 42;    // Klappt
if(true) let i = 42;    // SyntaxError: Illegal let declaration in unprotected statement context
if(true){ let i = 42; } // Klappt

Ansonsten verhält sich let ziemlich genau wie var und unterliegt auch den gleichen Einschränkungen – auch let window = 42 kann in einem Browser das Window-Objekt nicht überschreiben. Insgesamt ist let also nichts weiter als ein repariertes var, dass im JavaScript-Code der Zukunft ersteres in den meisten Fällen anstelle von var ersetzt werden dürfte.

Lösung 2: const statt var

Mit const lassen sich echte Konstanten anlegen, die auch wirklich nicht überschrieben werden können:

const KONSTANTE = 42;
KONSTANTE = 1337; // TypeError: Cannot assign to read only property 'KONSTANTE'

Genau wie let-Variablen sind auch const-Konstanten an ihren Block gebunden:

if(true){
    const KONSTANTE = 42;
}
console.log(KONSTANTE); // ReferenceError: KONSTANTE is not defined

Anders als Variablen (egal ob let oder var) müssen Konstanzen logischerweise auch immer mit einem Wert initialisiert werden:

var foo;   // Kein Problem
let bar;   // Kein Problem
const BAZ; // SyntaxError: Unexpected token ;

Auch wenn JavaScript nun echte Konstanten kennt, ist es sinnvoll, auch bei deren Verwendung weiterhin den Bezeichner komplett groß zu schreiben – so ist immer klar, wann man es mit einer Variablen oder einer Konstanten zu tun hat.

Der Status

Über let und const besteht in der ES6-Arbeitsgruppe weitgehend Konsens und die noch offenen Fragen (nachzulesen auf den entsprechenden Wiki-Seiten) betreffen allesamt Sonderfälle. Aufhalten lassen werden sich diese Features nicht mehr. Und so zeigt die allmächtige Kompatibilitätstabelle schon recht viel grün, doch echte Unterstützung für let und const findet sich zur Zeit nur in den V8-Engines von Chrome ab Version 18 und Node.js. Ab Firefox Version 2.0 sowie einigen anderen Browsern existieren auch Implementierungen von let und const, die jedoch nicht mit dem ES6-Standard kompatibel sind und die man daher weiträumig umfahren sollte.