Dieser Artikel ist Teil einer Serie:
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)
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?Philipp ¶
10. Mai 2011, 15:00 Uhr
Warum kein Update auf 10.5???
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)
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?Peter Kröner ¶
10. Juni 2012, 10:32 Uhr
So?
Keine Garantie dass das in allen Browsern funktioniert, hab es nur schnell in Chrome gehackt.