Eigenschaftsdeskriptoren sind ein neues Konzept in ES5. Ihre Funktion besteht darin, den Eigenschaften von Objekten mehr Kontrolle zu verleihen.
Object.defineProperty
Um Eigenschaftsdeskriptoren zu untersuchen, müssen wir zunächst über die Methode Object.defineProperty sprechen. Der Zweck dieser Methode besteht darin, neue Eigenschaften für das Objekt zu definieren oder vorhandene Eigenschaften zu ändern. Sein Prototyp ist wie folgt:
Object.defineProperty(obj, prop, descriptor)
Anwendungsbeispiel:
var obj = { };
Object.defineProperty(obj, 'attr', { value: 1 });
Der obige Code fügt dem obj-Objekt ein Attribut namens attr mit dem Wert 1 hinzu. Entspricht:
var obj = { };
obj.attr = 1;
Im Vergleich dazu scheint die Schreibmethode von Object.defineProperty komplizierter zu sein. Sein größtes Geheimnis liegt jedoch in seinem dritten Parameter.
Datendeskriptor
Angenommen, wir möchten, dass attr ein schreibgeschütztes Attribut ist, können wir den beschreibbaren Datendeskriptor hinzufügen:
var obj = { };
Object.defineProperty(obj, 'attr', {
Wert: 1,
beschreibbar: falsch
});
console.log(obj.attr);
obj.attr = 2; // fehlgeschlagen
console.log(obj.attr);
Wenn Sie das obige Programm ausführen, können Sie feststellen, dass der zweimal gedruckte Wert von attr 1 ist, was bedeutet, dass das Schreiben des Attributs fehlgeschlagen ist. Ein solches Ergebnis wäre jedoch etwas rätselhaft, da die Zuweisungsanweisung ausnahmslos nicht ausgeführt werden konnte, wenn ein solches Problem in einem großen Codeabschnitt auftritt, wäre es schwierig, es zu beheben. Tatsächlich führt die bloße Ausführung des Codes im strikten Modus zu einer Ausnahme:
'use strict'; // Strikten Modus aufrufen
var obj = { };
Object.defineProperty(obj, 'attr', {
Wert: 1,
beschreibbar: falsch
});
obj.attr = 2; // Ausnahme auslösen
Werfen wir einen Blick auf einen anderen aufzählbaren Datendeskriptor, der steuern kann, ob die Eigenschaft aufgezählt werden kann. Wenn Sie einfach ein Attribut definieren, kann dieses Attribut in einer for...in-Schleife aufgezählt werden:
var obj = { };
obj.attr = 1;
for (var i in obj) { console.log(obj[i]); }
enumerable kann es „verstecken“:
var obj = { };
Object.defineProperty(obj, 'attr', {
Wert: 1,
aufzählbar: false
});
for (var i in obj) { console.log(obj[i]); }
Wenn Sie den obigen Code ausführen, werden Sie feststellen, dass die Konsole nichts ausgibt, da das Attribut attr derzeit nicht aufgezählt werden kann.
An dieser Stelle haben Sie möglicherweise eine Frage: Kann der Attributdeskriptor geändert werden? Kann beispielsweise eine schreibgeschützte Eigenschaft wieder als beschreibbar definiert werden? Tatsächlich hängt dies von einem anderen konfigurierbaren Datendeskriptor ab, der steuert, ob der Eigenschaftsdeskriptor geändert werden kann.
var obj = { };
Object.defineProperty(obj, 'attr', {
Wert: 1,
beschreibbar: falsch,
konfigurierbar: true
});
Object.defineProperty(obj, 'attr', {
beschreibbar: wahr
});
obj.attr = 2;
Der obige Code definiert attr zunächst als schreibgeschütztes Attribut und definiert es dann als beschreibbar neu. Das Schreiben an attr ist also erfolgreich.
Zugriffsdeskriptor
Zugriffsdeskriptoren ähneln objektorientierten Get/Set-Accessoren.
var obj = { };
Object.defineProperty(obj, 'attr', {
set: function(val) { this._attr = Math.max(0, val); },
Holen Sie sich: function() { return this._attr;
});
obj.attr = -1;
console.log(obj.attr); // 0
Im obigen Codeteil wird der Zugriff auf attr tatsächlich zum Zugriff auf _attr, und der Mindestwert ist in der Set-Funktion auf 0 begrenzt.
Attributdeskriptor abrufen
Oben dreht sich alles um das Festlegen von Attributdeskriptoren. Wie erhält man also die festgelegten Deskriptoren? Object.getOwnPropertyDescriptor erledigt den Job.
var obj = { };
Object.defineProperty(obj, 'attr', {
Wert: 1,
beschreibbar: falsch,
konfigurierbar: true
});
var desc = Object.getOwnPropertyDescriptor(obj, 'attr');
console.dir(desc);
Objektkontrolle
Die zuvor erwähnte Object.defineProperty arbeitet mit den Eigenschaften des Objekts, während die drei unten genannten Methoden direkt mit dem Objekt arbeiten.
Object.preventExtensions kann verhindern, dass Objekte neue Eigenschaften haben:
var obj = { };
obj.attr = 1;
Object.preventExtensions(obj);
obj.attr2 = 2; //fail
Object.seal
kann dafür sorgen, dass das Objekt nur änderbare Attributwerte hat (wenn das Attribut schreibgeschützt ist, können auch die Attributwerte nicht geändert werden):
var obj = { };
obj.attr = 1;
Object.seal(obj);
obj.attr = 1.5;
obj.attr löschen; // fehlschlagen
Object.freeze
kann das Objekt völlig unveränderbar machen:
var obj = { };
obj.attr = 1;
Object.freeze(obj);
obj.attr = 1.5; // fehlgeschlagen
obj.attr2 = 2; //fail
Dann fragen Sie sich vielleicht: Woher wissen Sie, ob ein Objekt vor Erweiterungen geschützt, versiegelt oder eingefroren wurde? Die Antwort besteht darin, Object.isExtensible, Object.isSealed bzw. Object.isFrozen aufzurufen. Die Verwendung dieser drei Funktionen ist relativ einfach und nicht mehr umständlich.
Im Allgemeinen können Objekte durch Attributdeskriptoren strenger gesteuert und die Genauigkeit der Programmlogik gestärkt werden. Der einzige Nachteil besteht darin, dass ES5 grundsätzlich nur in IE9 implementiert ist (IE9 unterstützt den strikten Modus noch nicht). IE8 Obwohl der Anteil noch relativ hoch ist, können diese Dinge derzeit nur in mobilen Browsern und Node.js verwendet werden.