ECMAScript 5 führt nicht nur komplett neue Konzepte wie den Strict Mode oder schreibgeschütze Objekte ein, sondern besteht zum einem großen Teil aus kleinen Helferlein. Viele dieser neuen Funktionen kommen einem aus den verbreiteten JavaScript-Frameworks bekannt vor und eigentlich könnte sie sich jeder halbwegs fähige Programmierer selbst mit JavaScript-Bordmitteln zusammenstricken. Doch wenn diese oft gebrauchten Funktionen durch ES5 verbindlich standardisiert und fest in den Browser eingebaut werden, braucht man eben genau das nicht tun und kann sich auf überall einheitliches Verhalten verlassen – und das ist doch eigentlich ganz fein.

Neue Helferlein gibt es für fast alle Bestandteile der Sprache, wobei die neuen Funktionen für Arrays und Objekte den größten Brocken ausmachen. In diesem Artikel geht es dabei zunächst um Objekte, denn für diese hat ES5 neben den aus Teil drei bekannten Funktionen zur Steuerung der Erweiterbarkeit von Objekten und Eigenschaften (Object.defineProperty, Object.freeze, Object.isSealed usw.) noch weitere Neuheiten an Bord.

Prototypen bei Objekterstellung festlegen

Es ist recht umständlich, ohne ES5 ein Objekt mit einem bestimmten Prototypen zu erstellen. Zunächst muss der Objekt-Constructor angelegt werden, dann kann der Prototyp bestimmt werden und erst danach darf man sein Objekt erstellen:

var Vogel = {
    federn: true
}

var Huhn = function(){};
Huhn.prototype = Vogel;

var meinHuhn = new Huhn();
meinHuhn.eier = 42;

Mit dem neuen Object.create() (MDC-Docs) ist es möglich, diesen ganzen Prozess in einem Statement abzuwickeln – property descriptor map für die Eigenschaften inklusive:

var meinHuhn = Object.create(Vogel, {
    eier: {
        value: 42,
        enumerable: true
    }
});

Das erste Argument ist der gewünschte Prototyp, das zweite die property descriptor map für die Eigenschaften. Als Prototyp kann entweder ein Objekt (auch ein leeres Objektliteral oder object.prototype) oder null angegeben werden.

Welchen Prototyp hat mein Objekt?

Mit dem in ES5 ebenfalls neuen Object.getPrototypeOf() (MDC-Docs) können wir uns vergewissern, dass Object.create() seine Arbeit ordnungsgemäß getan hat und dass unser Huhn wirklich Vogel als Prototyp hat:

Object.getPrototypeOf(meinHuhn); // Objekt "Vogel"

Object.getPrototypeOf() ist der standardkonforme Ersatz für die sonst an dieser Stelle gern verwendete Nicht-Standard-Eigenschaft __proto__.

Eigene Objekteigenschaften abfragen

Eine weitere Aufgabe, die ohne ES5 immer recht aufwändig ist, ist die Abfrage aller (eigenen) Eigenschaften eines Objekts. Man muss eine for-in-Schleife bemühen und in diesem noch eine Abfrage einbauen, die die gesamte Konstruktion auf die eigenen Eigenschaften des Objekt beschränkt und die vererbten Eigenschaften ausschließt:

var eigenschaften = [];
for(prop in meinHuhn){
    if(meinHuhn.hasOwnProperty(prop)){
        eigenschaften.push(prop);
    }
}

In ES5 geht das viel einfacher: Object.getOwnPropertyNames (MDC-Docs) und Object.keys (MDC-Docs) geben je ein Array mit den Eigenschaftsnamen des Objekts zurück. Object.getOwnPropertyNames gibt alle Eigenschaftsnamen des Objekts zurück – auch jene, die nicht enumerable (siehe Teil drei) sind. Hingegen beschränkt sich Object.keys auf Eigenschaftsnamen, die auch enumerable sind und verhält sich damit ziemlich genau wie die althergebrachte for-in-Schleife:

var Vogel = {
    federn: true
}

var meinHuhn = Object.create(Vogel, {
    eier: {
        value: 42,
        enumerable: true
    },
    hackordnung_level: {
        value: 6,
        enumerable: false
    }
});

Object.keys(meinHuhn);                // ["eier"]
Object.getOwnPropertyNames(meinHuhn); // ["eier", "hackordnung_level"]

Die federn-Eigenschaft des Prototypen fehlt in beiden Fällen, da die Funktionen jeweils nur die eigenen Objekteigenschaften abfragen.

Reservierte Namen als Objektschlüssel

Ein letztes kleines Extra: in ES5 dürfen reservierte Namen für Objekteigenschaften verwendet werden:

// Funktioniert nicht
var class = "foo";

// Funktioniert!
var foo = {
    class: "bar"
}

Das kann man zwar für inkonsequent halten, dürfte aber in letzter Konsequenz eher die allgemeine Verwirrung reduzieren als erhöhen – schließlich hagelt es weniger (mehr oder minder) grundlose Fehler.

Ausblick

Sieht man einmal von Opera ab, so bietet uns die allmächtige Kompatibilitätstabelle ein überwiegend grünes Bild was die neuen Funktionen für Objekte angeht – selbst der IE9 lässt sich nicht lumpen. Sogar noch besser sieht es im Array-Bereich aus, denn da spielt auch Opera mit. Arrays nehmen wir uns dann im nächsten Teil der Serie vor.