ECMAScript 5, die nächste Version von JavaScript – Teil 4: Kleine Helferlein für Objekte

Achtung: dieser Beitrag ist alt! Es kann gut sein, dass seine Inhalte nicht mehr aktuell sind.

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.

Kommentare (5)

  1. Benjamin

    9. Mai 2011, 18:51 Uhr

    Das sieht ja nach vielen schönen neuen Features aus, toll!

    Allerdings habe ich ein kleines Problem was die ganzen Kompatibilitätstests angeht, nicht nur hier, sondern auch bei CSS3 und HTML5: es wird immer so schön gesagt 'alle modernen browser kommen mit', wobei aber FF 3.6 und Safari 4 nicht mehr beachtet werden. Das schließt Menschen mit MacOS 10.4 aus. Da gehört Safari 5 nicht dazu und Mozilla hat ab FF4 den Support für 10.4 eingestellt (offiziell aus Performancegründen). Und dabei ist 10.4 doch noch gar nicht sooo alt (3 Jahre). huch das sind ja doch schon 5 Jahre. Naja jedenfalls betrifft es alle die in den ersten Generationen eine intel-Mac gekauft haben. Ich schau da jetzt halt ziemlich in die Röhre und ich bin sicher das betrifft nicht nur mich... oder? hat da jemand relevante daten drüber?

  2. Philipp

    10. Mai 2011, 15:00 Uhr

    Warum kein Update auf 10.5???

  3. Benjamin

    14. Mai 2011, 15:40 Uhr

    Naja, bisher fand ich 115 Euro ein wenig viel nur dann in einem Jahr wieder abgehängt zu werden. Ich sehe ja ein dass ich eine alte Maschine hab, aber ich ärgere mich darüber, dass mir quasi die lange Haltbarkeit der Hardware 'zum Verhängnis' wird... letzten Endes ist mein Rechner ja noch top in Schuss, nur lassen nach und nach alle möglichen Softwareprojekte die Unterstützung fallen. (Firefox ist da natürlich nicht allein)

  4. Christian Müller

    9. Juni 2012, 22:57 Uhr

    Wäre es irgendwie möglich, Object.create() und ähnliches in Verbindung mit Konstruktormethoden zu nutzen?

  5. Peter Kröner

    10. Juni 2012, 10:32 Uhr

    So?

    var Foo = function(){
        var proto = Object.getPrototypeOf(this);
        return Object.create(proto, {
            baz: {
                value: 42,
                enumerable: true
            }
        });
    };
    Foo.prototype = {
        bar: 42
    };
    
    var meinFoo = new Foo();

    Keine Garantie dass das in allen Browsern funktioniert, hab es nur schnell in Chrome gehackt.

Die Kommentarfunktion ist seit Juli 2014 deaktiviert, weil sie zu sehr von Suchmaschinenoptimierern für manuellen Spam mißbraucht wurde. Wenn du Anmerkungen oder Fragen zum Artikel hast, schreib mir eine E-Mail oder melde dich via Twitter.

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