Erklärbär-Termine für Juli, August und September

In den nächsten Monaten bin ich vor allem mit Inhouse-Schulungen beschäftigt, aber es gibt auch wieder einen öffentlichen Erklärbär-Termin:

  • 3. - 5. August in München: Moderne Frontendentwicklung (HTML5, CSS3, JavaScript). HTML5 … und dann? Die Schulung „Moderne Frontendentwicklung“ ist der Nachfolger meiner klassischen HTML5-Schulung und hebt erfahrene Webentwickler auf das nächste Level. Der Kurs behandelt die seit HTML5 neu hinzugekommenen Webstandards (z.B. Web Components), bespricht Tools und Best Practices, gibt Tipps für den Einsatz neuer Features in heutigen Browsern und bietet auch einen Ausblick in die weitere Zukunft der Web-Plattform.

Termine unpassend, Orte alle zu weit weg und Programme nicht genehm? Ich komme auch gerne mit einem maßgeschneiderten Workshop vorbei – mich kann man ganz einfach mieten!

Fragen zu HTML5 und Co beantwortet 20 - Graustufen, SQL-Datenbank, Tail Recursion, Arrow Functions in Klassen

Der beliebte Fragen-beantwort-Service von Erklärbär Enterprises meldet sich zurück, heute mit CSS-Filtern, HTML5-Datenbanken und zwei Fragen zu ECMAScript 6. Wenn auch euch Fragen zu Frontend-Themen wie HTML5, CSS3, JavaScript, Tools und ähnlichem habt, dann schickt sie mir: eine E-Mail oder ein Tweet genügen! Die Fragen werden beantwortet, gesammelt und wenn vier Antworten zusammen gekommen sind, folgt die Veröffentlichung.

Cross-Browser-Graustufen für Bilder?

Gibt es eine zuverlässige Möglichkeit (auch für den IE) Bilder via CSS oder JavaScript grau einzufärben?

In jedem modernen Browser mit Ausnahme der Internet-Explorer-Familie ist ein Graustufen-Effekt mit CSS-Filtern (Can I Use) ein Kinderspiel. Mit Filtern kann man jeden denkbaren SVG-Filter auf jedes beliebige Element in einer Webseite anwenden und für die häufigsten Anwendungsfälle wie eben Graustufen gibt es eine praktische Kurzschreibweise, bei der man sich den SVG-Part ersparen kann (Demo auf Codepen):

img {
  -webkit-filter: grayscale(100%);
  filter: grayscale(100%);
}

Dummerweise machen die neueren Internet Explorer nicht mit. Die IE 6-9 kann man mit einer vergleichsweise simplen Code-Transformation, wie sie in Schepps CSS-Filters-Polyfill vollführt wird, bedienen, denn diese unterstützen eine proprietäre Syntax mit ähnlichen Fähigkeiten wie filter. Allerdings wurde diese proprietäre Syntax im Zuge des großen Aufräumens aus dem IE 10 entfernt, so dass es dort keine Möglichkeit gibt, Graustufen-Filter mit CSS allein umzusetzen.

Einzig denkbarer Ausweg: das <canvas>-Element. Dieses funktioniert auch im IE9 und könnte genutzt werden, um normale <img>-Elemente zu klonen und sie im Zuge dessen in Graustufen zu konvertieren. Eine kleine Demo gibt es hier. Die Haken an dieser Methode sind die JavaScript-Abhängigkeit und natürlich, dass sich hiermit nur Bild-, Canvas- und Video-Elemente in Graustufen darstellen lassen – CSS-Filter funktionieren auf allen Elementen.

Was ist Tail Recursion? Und was hat das mit ECMAScript 6 zu tun?

Was ist „Tail Recursion“ und warum liest man im ES6-Kontext ständig davon?

Gibt man einer heutigen JavaScript-Engine eine Aufgabe, die viel Rekursion beinhaltet, bekommt man häufig einen Fehler der Marke maximum call stack size exceeded oder too much recursion vorgesetzt. Das liegt einfach darin begründet, dass der Call Stack, der die Liste der sich einander aufrufenden Funktionen beinhaltet, nicht beliebig groß werden kann. Beispiel:

function f(x){
  x++;
  if(x === 5000000){
    return 'Fertig nach ' + x + ' Aufrufen von f()';
  }
  return f(x);
}

console.log(f(0));
// Error: Maximum call stack size exceeded

Hier ruft f() immer wieder sich selbst auf und der Browser muss sich für jeden Aufruf das jeweils übergebene x und vieles mehr merken. Der Call Stack wächst und wächst, denn als fertig gilt ein Aufruf von f() erst, wenn alle enthaltenen f()-Aufrufe fertig sind. So wird der Call Stack immer größer, bis er irgendwann ein ein Limit stößt und es laut knallt.

Allerdings muss es in diesem Beispielcode eigentlich nicht zwangsläufig knallen, denn die Rekursion findet in f() als allerletzte Aktion statt – es handelt sich um einen soganannten Tail Call. Solche Tail Calls können durch die den Interpreter oder Compiler einer Programmiersprache so optimiert werden, dass sie keinen Extra-Platz auf dem Call Stack benötigen und viel tiefere Rekursion möglich wird. Optimiert könnte das obrige Programm genau so gut wie folgt aussehen:

function f(_x){
  var _again = true;
  _function: while(_again){
    _again = false;
    var x = _x;
    x++;
    if(x === 5000000){
      return 'Fertig nach ' + x + ' Aufrufen von f()';
    }
    _x = x;
    _again = true;
    continue _function;
  }
}

console.log(f(0));

Die rekursive Konstruktion wird zu einer Schleife umgebogen, belastet den Call Stack nicht mehr und kann daher wesentlich länger laufen. Voraussetzung für derartige Optimierungen ist lediglich, dass die Rekursion wirklich die aller-allerletzte Aktion in der fraglichen Funktion ist.

Mit ECMAScript 6 hat das Ganze nur insofern zu tun, als dass ab dieser Version die Optimierung von Tail Calls für alle JavaScript-Engines verbindlich vorgeschrieben sein wird. Bis das in allen Browsern der Fall ist, klappt es bei so einfacheren Fällen wie dem obrigen Beispiel auch mit Babel.

SQL-Datenbank im Browser?

Ich möchte zur Sicherung der Offline-Funktionalität meine Webapp mit einem MySQL-Backend synchronisieren. Hierbei müssten auch Abfragen mit JOINS möglich sein, also über mehrere Tabellen. Gibt es eine passende Browsertechnologie hierfür?

Eine SQL-Datenbank im Browser gibt es nicht und wird es nie geben. Die Spezifaktion für die Web SQL Database ist seit 5 Jahren tot und die Browserunterstützung wird nicht mehr besser werden – eher schlechter. Die moderne Alternativ-Technologie Indexed DB (Specs, Can I use) hingegen ist gesund und munter, ist aber auch eine NoSQL-DB, bei der es prinzipbedingt Dinge wie Joins nicht gibt.

Die Lösung besteht wie so oft darin, JavaScript auf das Problem zu werfen. Libraries wie Lovefield implementieren auf Basis der Indexed DB eine Query-Sprache, die zwar nicht ganz SQL ist, aber ungefähr das gleiche auszudrücken vermag.

ES6: Arrow Functions in Klassen?

Wie kann ich in ES6 Arrow Functions in Klassen benutzen? Ich habe eine Klassen-Methode getBar(), die immer das this des von der Klasse erzeugten Objekts benutzen soll. Arrow Functions scheinen in Klassen syntaktisch nicht zugelassen zu sein, aber ich möchte gerne Klassen-Methoden als Callbacks verwenden können ohne ständig fooInstance.getBar.bind(fooInstance) schreiben zu müssen.

Zur Verdeutlichung: das Ziel ist, dass das Folgende funktioniert:

class Foo {
  constructor(){
    this.bar = 'test';
  }
  getBar(){
    console.log(this.bar);
  }
}

var f = new Foo();
setTimeout(f.getBar, 1000);

Ohne f.getBar.bind(f) oder eine ähnliche Konstruktion wird das allerdings nicht funktionieren – Arrow Functions können hier nicht helfen. Das Problem ist, dass die Klassensyntax von ES6 nur syntaktischer Zucker für die althergebrachten JS-Prototypen ist. Der obrige ES6-Code entspricht (grob) dem folgenden ES5:

function Foo(){
  this.bar = 'test';
}
Foo.prototype.getBar = function(){
  console.log(this.bar);
}

var f = new Foo();
setTimeout(f.getBar, 1000);

Hier sieht man sofort, dass getBar() nicht auf ein this festgenagelt werden kann, da das Ziel-this zum Zeitpunkt der Definition getBar() nicht bekannt ist bzw. getBar() als Prototypen-Methode mit den unterschiedlichen this der unterschiedlichen Foo-Instanzen arbeiten muss. Es handelt sich hier also um keine syntaktische, sondern eine ganz grundsätzliche Hürde.

Was also tun? Am besten tatsächlich brav jedes Mal f.getBar.bind(f) verwenden, denn das ist am einfachsten und am deutlichsten. Alternativ könnte man natürlich auch jeder Instanz eine eigene getBar()-Methode geben, die sich das this per Closure merkt:

class Foo {
  constructor(){
    this.bar = 'test';
    this.getBar = function(){
      console.log(this.bar);
    }.bind(this)
  }
}

var f = new Foo();
setTimeout(f.getBar, 1000);

Insgesamt ist bind() aber schon die sauberere Lösung.

Weitere Fragen?

Auch eure Fragen zu HTML(5), CSS(3), JavaScript und anderen Webtechnologien beantworte ich gerne! Einfach eine E-Mail schreiben oder Twitter bemühen und ein bisschen Geduld mit der Antwort haben. Ansonsten kann man mich natürlich auch als Erklärbär zu sich kommen lassen.

Erfahrungsbericht: Leben und Arbeiten mit einer Smartwatch

Apple Watch by Pandyland
„Apple Watch“ by Pandyland

Smartwatches werden in meiner Filterblase überwiegend belächelt. Es reicht nicht einmal für die übliche Technikfeindlichkeit im Stile von das braucht doch kein Mensch und OMG WTF BND NSA Überwachung!!11 – es werden einfach nur Witze gemacht. Demnach dürften diese Dinger wirklich komplett egal sein, oder? Trotzdem kam mir vor kurzem die Idee, dass für mich ein solches Teil wirklich nützlich sein könnte. Und so habe ich mir eine Smartwatch geklickt und bin damit ein paar Tage durch die Gegend gewandet. Dieser Artikel ist weniger ein Tech-Review als vielmehr eine Erfahrungsbericht zum Konzept Smartwatch an sich. Es geht hier zwar um Android-Hardware, aber die Erkenntnisse sollten 1:1 auf das Apple-Universum übertragbar sein.

Motivation

Der eigentliche Anlass für die Anschaffung der Smartwatch war mein zunehmend nicht mehr zu gebrauchenes Galaxy S2. Das Telefon ist schlicht, flexibel, robust, konnte zweimal problemlos in Eigenregie repariert werden und hat mir jahrelang treu gedient. Allerdings ist es mittlerweile selbst für ruckelfreien Internetkonsum zu schwach, der Lack des Metallrahmens ist nur noch in Spuren nachweisbar und auch der Ersatzakku des Ersatzakkus ist am Ende. Ein neues Telefon sollte her, am besten ein 1:1-Ersatz mit mehr Power. Sowas scheint aber nicht angeboten zu werden. Heutzutage ist meist ist der Akku fest eingebaut und die Bildschirme haben Flächen, die man am besten in Vielfachen des Saarlandes angibt – einhändige Bedienung ausgeschlossen. Mir war nicht danach, dafür 500 Euro und mehr auf den Tisch zu legen.

Doch auch nach Monaten der Wartezeit kam kein mir genehmes Telefon auf den Markt. Und so kam ich auf die Idee, dass sich die zwei Hauptpunkte meines Anforderungskatalogs eventuell auch anders als über ein zu 100% passendes Telefon erfüllen lassen könnten:

  1. Ursprüngliche Anforderung: Auswechselbarer Akku!
    Motivation: Nicht 500 Euro für ein Telefon bezahlen, das am Ende wegen seines Akkus in den Müll wandert, obwohl der Rest noch funktioniert.
    Alternativlösung: Weniger teures Telefon kaufen, bei dem mir die frühzeitige Verschrottung nicht so sehr schmerzt.
  2. Ursprüngliche Anforderung: Kleines Telefon für einhändige Bedienung!
    Motivation: Unterwegs, d.h. zu Fuß mit Gepäck in der Hand müssen Navigation, Gate-Check, E-Mail-Empfang und dergleichen bequem möglich sein.
    Alternativlösung: „Normales“ großes Telefon anschaffen und mit dem durch den Billigkauf gesparten Geld einen Second Screen für das Telefon, also eine Smartwatch finanzieren.
Meine LG G Watch R
Meine LG G Watch R mit Woto Watch Face

Diesen Plan habe ich in der Tat umgesetzt. Günstige Riesen-Telefone bekommt man heutzutage direkt vom chinesischen Hersteller, die durch die Umgehung von Zwischenhändlern wie Samsung und Apple billiger verkaufen können. In meinem Fall ist es das monströse OnePlus One geworden. Das Telefon ist nicht die ober-absolute Crème de la Crème, aber einem 350-Euro-Gaul (und das ist schon die teuerste Variante) schaut man nicht so genau ins Maul. Dazu habe ich nach dem Studium einiger Uhr-Reviews eine LG G Watch R (Amazon-Link) für rund 200 € geklickt.

Erfahrungsbericht

Für mich und meine Luxusprobleme funktioniert die Kombination aus Riesentelefon und Hilfscomputer am Handgelenk ganz hervorragend. Wenn ich entspannt im Zug sitze, habe ich ein größeres Telefon, woran man sich sehr schnell gewöhnt. Viele lästige Zwischendurch-Am-Handy-Herumfummel-Momente werden hingegen durch die Uhr abgefangen:

  • Nachricht geht ein? Auf der Uhr kann man schnell eine Notification-Vorsortierung vornehmen und entscheiden, ob man das Telefon in der Hand nehmen muss oder nicht. Wurde ein Tweet gefavt? Zur Kenntnis nehmen und nichts weiter tun. Eine E-Mail berichtet, dass auf einer relevanten Github-Issue ein „+1“-Kommentar eingegangen ist? Direkt von der Uhr aus die E-Mail löschen. Eine SMS der Airline berichtet, dass dein Flug gestrichen wurde? Jetzt ist es vielleicht der Moment gekommen, zum Telefon zu greifen und nachzuforschen. Ansonsten kann der Klotz in der Tasche liegen bleiben und Mainframe spielen. Welche Apps Benachrichtigungen an die Uhr durchreichen können, ist frei konfigurierbar.
  • Für Navigation in einer fremden Stadt braucht man eigentlich keine computergestützte Karte – es reicht, wenn man gesagt bekommt, wann man links abbiegen muss. Ein entsprechendes Vibrations-Signal reicht da eigentlich und ein entsprechender Pfeil passt auch bequem auf das Smartwatch-Display. Praktisch ist dabei auch, dass der Blick auf die Uhr nicht so sehr ablenkt, dass man dabei je gegen einen Laternenpfahl laufen könnte.
  • Ein Timer oder Alarm lässt sich schnell direkt an der Uhr einstellen und hat den großen Vorteil, wirklich nur am eigenen Handgelenk stattzufinden. Niemand bekommt (anders als beim laut summenden Telefon) mit, dass man gerade an etwas erinnert wird, d.h. niemand fühlt sich genötigt, mitten im Satz ein Gespräch abzubrechen. Ich nutze diese Funktion vor allem, um mich bei Schulungen an Pausen erinnern zu lassen. Der Alarm geht 15 Minuten vor der Pause los, so dass bequem noch das aktuelle Thema zu Ende bringen kann.
  • Eingeschränkt nützlich scheint mir die Uhr auch für das Lesen von Notizen geeignet zu sein. Normalerweise bin ich in Sachen Notizen, Einkaufszetteln und Todo-Listen ganz klar im Papier-Camp, da sich Kugelschreiber und Papier einfach schneller bedienen lassen als irgendwelche Apps oder Gadgets. Aber um sich an einem fremden Bahnhof oder auf einem Flughafen daran zu erinnern, wo man eigentlich nochmal hin wollte, scheint mir die Uhr eine handliche Alternative zu sein. Die meisten Apps sind nicht besonders gut darin, Text auf dem winzigen Display darzustellen, aber mit Google Keep klappt es ganz passabel.
  • Auch Mediensteuerung und Lautstärkeregelung funktionieren recht komfortabel.

Die Uhr ist also eine hübsche Ergänzung wenn es darum geht, Internet-Informationsfluss vorzufiltern, sich an Dinge erinnern zu lassen oder sich zurechtzufinden – jeweils ohne an einem unhandlichen Telefon herumzufummeln.

Beklagen kann ich allerhöchstens ein paar technische Details der LG G Watch R und von Android Wear, Googles Smartwatch-App für Telefone. Die Uhr wie das Telefon jeden Abend aufzuladen ist kein Problem und der Akku hält bei moderater Benutzung auch zwei Tage und mehr. Wenn es überhaupt ein Strom-Problem gibt, dann noch am ehesten auf Seiten des ständig mit Bluetooth funkenden Telefons. Die LG G Watch R braucht ein spezielles Ladegerät und möchte man davon mehr als ein besitzen (weil man wie ich stets eins im Koffer liegen haben möchte), ist man auf windige eBay-Händler angewiesen. Kabelloses Laden oder USB wäre angenehmer. Ein Helligkeitssensor wäre eine sinnvolle Erweiterung der Hardware gewesen, denn ohne einen solchen Sensor ist die Display-Helligkeit nur fest einzustellen. Dank des starken Akkus ist das kein großes Problem, denn nichts spricht dagegen, die Helligkeit einfach voll aufzudrehen. Auch ohne einen platzhungrigen USB-Anschluss ist die Uhr für meinen persönlichen Geschmack recht groß. Gemessen an anderen Herrenarmbanduhren ist sie das zwar nicht, aber ich bin eben eine halbe Portion und da wirkt das Gerät schon ein wenig klotzig. Und das Lederarmband finde ich recht langweilig, sollte sich aber vom Fachmann ohne weiteres ersetzen lassen. Wirklich gravierende Nachteile sehen anders aus, so dass ich mit dem Kauf der Uhr ganz zufrieden bin. Ärgerlicher ist die in vielerlei Hinsicht hakelige um umständliche Android-Wear-Software, aber so ist das eben bei Android – und nach dem erstmaligen Einrichten ist das auch egal.

Braucht man sowas?

Wäre auch Otto Normalverbraucher mit der Anschaffung eines vergleichbaren Geräts gut beraten? Da bin ich mir nicht so sicher. Ich bin ein effizienzvernarrter Nerd mit zu vielen Internetkontakten, der ständig unterwegs ist und das Glück hat, mal eben 200 Euro übrig zu haben. Bei einer Smartwatch handelt es sich um einen Hilfscomputer am Handgelenk, was mit einer herkömmlichen Armbanduhr meiner Meinung nach noch weniger gemeinsam hat, als ein Telefon mit einem verkabelten Wählscheiben-Telefon.

Ein Smartphone ist nicht in erster Linie ein Ersatz für ein altmodisches Kabel-Telefon oder 90er-Jahre-Handy. Es stellt vielmehr einen tragbaren Internetanschluss dar, mit dem sein Besitzer jederzeit mit Freunden oder der Arbeit in Kontakt bleiben kann. Das kann für so ziemlich Jedermann ein Gewinn sein. Den Hilfscomputer hingegen kann man meiner Meinung nach vor allem dafür gebrauchen, zu viel Internet etwas besser zu managen. Die Navigations-Funktion ist ein höchstens ein hübsches Extra und den ganzen Fitness-Krempel kann ich nicht wirklich einschätzen, da sowas bei mir immer noch mit Stift und Papier bzw. Excel-Tabellen erfasst wird. Als wirkliches Must-Have-Killerfeature erscheint mir das aber auch nicht. Die Kehrseite einer Smartwatch ist, dass sie mit der normalen Armbanduhr durchaus ein vorhandenes Accessoire vom Handgelenk verdrängt. Letztere ist oft ein Schmuckstück und ggf. Statussymbol, das seinen Wert über Jahre behält oder gar noch steigert. Der Hilfscomputer ist ein rapide veraltendes Stück Kunststoff und/oder Blech. Das sollte man nicht verwechseln und man sollte sich genau überlegen, ob man für sowas die mehreren hundert Euro wirklich übrig hat.

Fazit: die Smartwatch macht meinen persönlichen Alltag ein klein wenig effizienter und das ist mir die 200 Euro wert gewesen. Sich vor dem Kauf eines solchen Gerätes gründlich zu überlegen, was damit anzustellen gedenkt, ist aber keine schlechte Idee. Es geht bei diesen Geräten nicht um Armbanduhren (denn Armbanduhren sind die im Vergleich zu Smartwatches besseren Armbanduhren) sondern um Miniatur-Hilfscomputer der allerersten Generation.

ECMAScript 6: Symbols

Ein Wiedergänger unter den JavaScript-Patterns ist die Idee, man könnte doch die Prototypen von Built-Ins (z.B. Function, Array) und Host Objects (wie Element.prototype) erweitern, um Library-Funktionalität direkt an Objekte anzubauen. Macht man das, handelt man sich mehrere mögliche Probleme ein. Möglicherweise gibt es (jetzt oder in Zukunft) anderen Code im Projekt, der sich darauf verlässt, dass Objekte nur exakt jene Eigenschaften haben, die der Standard vorgibt. Oder möglicherweise gibt es (jetzt oder in Zukunft) Code im Projekt, der eine genau gleich benannte Erweiterung in die gleichen Objekte einbauen möchte. Oder möglicherweise programmiert eine halbwegs erfolgreiche Library und belegt damit in Zukunft einen Eigenschafts-Namen, den zukünftige ECMAScript-Standards gern benutzt hätten. Letzteres ist in ES6 passiert – dort sollte Array.prototype.contains() eingeführt werden, doch weil Mootools diesen Namen einst besetzt hat, musste die Funktion für ES6 in Array.prototype.includes() umbenannt werden.

Dieses Problem kann man schrittweise abschwächen; macht man die neu an das Objekt gebaute Eigenschaft non-enumerable, taucht sie z.B. nicht mehr in for-in-Schleifen auf und reduziert damit etwas ihr eigenes Kollisionspotenzial. Aber eine wirklich halbwegs saubere Lösung gibt es erst mit den in ECMAScript 6 eingeführten Symbols.

In Variablen gespeicherte Strings kann man bekanntlich als Eigenschaftsnamen für Objekte einsetzen:

// Das ging schon immer
var o = {};
var x = 'Foo';
o[x] = 42;

// Das ist neu in ES6
var p = {
  [x]: 42
};

In ECMAScript 6 gibt es eine spezielle Art von Objekten, die anstelle von Strings als Eigenschaftsnamen verwendet werden können. Diese Objekte heißen Symbols und können genau wie die Strings im obrigen Beispiel benutzt werden:

var o = {};
var x = Symbol();
o[x] = 42;

var p = {
  [x]: 42
};

Symbols funktionieren auf den ersten Blick also wie Strings, haben aber mehrere entscheidende Unterschiede. So sind Symbols sind per Definition einzigartig. Code, der keinen Zugriff auf ein Symbol hat, kann die damit gesetzten Werte nicht ohne weiteres auslesen:

var o = (function(){
  var x = Symbol();  
  return {
    [x]: 42
  };
})();

// Wie soll man an den Wert kommen?

// Das funktioniert nicht, Symbols are einzigartig
var x = Symbol();
console.log(o[x]); // undefined

Symbols sind außerdem immer non-enumerable und tauchen daher nicht in for-in-Schleifen auf. Sie verweigern sich auch jedem Versuch, sie in einen String zu verwandeln um irgendwie an den „wahren Wert“ hinter einem Symbol zu kommen oder es zu klonen. Symbols selbst sind der einzig wahre Wert und sie sind per Definition einzigartig.

Symbols kann man für viele nützliche Dinge gebrauchen. Die ECMAScript-Spezifikationen nutzen Symbols extensiv für den internen Aufbau der Sprache. Was den Hausgebrauch angeht sind Symbols super, um „private“ Instanzvariablen auf Objekten unterzubringen, ohne diese selbst in Closures zu platzieren:

// Keine Chance, die 42 zu überschreiben!
var o = (function(){
  var x = Symbol();  
  return {
    [x]: 42,
    getX: function(){
      return this[x];
    }
  };
})();

Aber auch öffentliche Symbols können nützlich sein. So könnte eine Library ein öffentliches Symbol anbieten, das Nutzer der Library nutzen können, um bestimmte Funktionen gezielt zu überschreiben. Theoretisch könnte diese Rolle auch ein String übernehmen, aber diese String-Eigenschaft wäre (wenn ich explizit anders definiert) in for-in-Schleifen sichtbar und sie würde bis in alle Ewigkeit eben jenen String-Namen als Objekt-Eigenschaft belegen und ggf. so manches Problem hervorrufen – man denke nur an __proto__. Symbols sind hier die sauberere Variante.

Symbols sind freilich nicht völlig privat: mit Object.getOwnPropertySymbols() kann man sich die Liste aller Symbol-Eigenschaften auf einem Objekt ausgeben lassen und darüber iterieren:

var o = (function(){
  var x = Symbol();  
  return {
    [x]: 42,
    getX: function(){
      return this[x];
    }
  };
})();

Object.getOwnPropertySymbols(o).forEach(function(sym){
  console.log(o[sym]); // > 42
});

Dass diese Funktion existiert, ist recht sinnvoll. Wer einen komplett privaten Wert haben möchte, hat ja bereits mit Closures das passende Werkzeug an der Hand. Symbols sind geheim genug für den Alltagsgebrauch und Object.getOwnPropertySymbols() macht das Debuggen und Testen von Objekten um einiges einfacher.

Allerdings bedeutet die Existenz von Object.getOwnPropertySymbols() auch, dass es eben nicht möglich ist, vorhandene Objekt zu erweitern und dabei jede Chance auf Kollisionen oder Missbrauch auszuschließen. Zwar gibt es nun keinen String-Eigenschaftsnamen mehr, der überschrieben werden könnte, aber mit einem Extra-Symbol wird plötzlich die Iterations-Schleife über das von Object.getOwnPropertySymbols() zurückgegebene Array länger, alte oder neue Symbols stehen nicht mehr an dem Index, an dem sie vorher waren und schon kann wieder eine ganze Menge kaputtgehen.

Und so bleibt es trotz Symbols bei der JavaScript-Grundregel Nummer 1: Prototyp-Objekten, die man nicht selbst gebaut hat, darf man nicht modofizieren, weil man nicht zu 100% ausschließen kann, das die Modifikation jetzt oder in Zukunft fremden Code kaputt macht.

Laut Kompatibilitätstabelle funktionieren Symbols heutzutage in Firefox, Chrome, dem kommenden nächsten Microsoft-Browser und sind hinter einem Flag auch in Node.js verfügbar. Transpiler wie Traceur und Babel versuchen ebenfalls Symbols zu implementieren, schaffen das bisher aber nicht perfekt.

Folgt mir!

Kauft mein Zeug!

Cover der HTML5-DVD
Infos auf html5-dvd.de, kaufen bei Amazon

Cover des HTML5-Buchs
Infos auf html5-buch.de, kaufen bei Amazon

Cover des CSS3-Buchs
Infos auf css3-buch.de, kaufen bei Amazon