Der Autor des Materials, dessen Übersetzung wir heute veröffentlichen, sagt, dass JavaScript-Objekte viele Dinge enthalten, deren Existenz Sie nicht einmal vermuten können, und die sie in der täglichen Arbeit verwenden. Objekte in JavaScript sind sehr einfach zu erstellen, bequem zu bearbeiten, sie scheinen verständlich und flexibel zu sein, und viele Programmierer denken einfach nicht daran, dass die Objekte tatsächlich nicht so einfach sind.

NB: Informationen aus der Veröffentlichung in der Praxis sollten sehr sorgfältig und unter Aufsicht erfahrener Kollegen angewendet werden.
Hier sprechen wir darüber, was in den Tiefen von Objekten verborgen ist, und diskutieren die Feinheiten der Arbeit mit ihnen.
Nachdem Sie dieses Material beherrschen, kennen Sie die Antworten auf die folgenden Fragen:
- Wie kann eine Eigenschaft eines Objekts nicht gelöscht werden?
- Was sind Eigenschaften mit Zugriffsmethoden und welche Funktionen haben sie?
- Wie macht man eine Immobilie unveränderlich oder versteckt?
- Warum sind einige Eigenschaften in
for-in
Schleifen oder in den Ergebnissen der Object.keys()
-Methode nicht sichtbar, und einige sind sichtbar? - Wie kann man ein Objekt vor Änderungen schützen?
- So verstehen Sie einen Code, der dem folgenden ähnelt:
obj.id = 5; console.log(obj.id)
Arten von Objekteigenschaften
▍ Datenspeichereigenschaften
Sie haben wahrscheinlich unzählige ähnliche Objekte erstellt:
const obj = { name: 'Arfat', id: 5 } obj.name
Die
name
und
id
Eigenschaften des
obj
Objekts werden als
obj
oder „
obj
“ bezeichnet. Dies sind bekannte Eigenschaften, die ständig im JavaScript-Code enthalten sind. Welche anderen Arten von Eigenschaften können Objekte haben?
▍ Eigenschaften mit Zugriffsmethoden
Diese Eigenschaften werden auch als Getter und Setter bezeichnet und sind auch in anderen Programmiersprachen wie C # oder Python zu finden. Eine Eigenschaft mit Accessor-Eigenschaft ist eine Kombination aus zwei Funktionen -
get
und
set
.
Wenn Sie solche Eigenschaften deklarieren, wird anstelle des herkömmlichen Konstrukts vom
:
die folgende Syntax verwendet:
const accessorObj = { get name() { return 'Arfat'; } }; accessorObj.name;
Schauen Sie sich das
accesorObj
Objekt an und vergleichen Sie es mit dem
dataObj
Objekt. Anscheinend zeigen sie jetzt das gleiche Verhalten. Bei der Beschreibung des ersten Objekts haben wir das Schlüsselwort
get
, gefolgt von der Deklaration der Funktion. Um auf eine ähnliche Eigenschaft zuzugreifen, obwohl sie durch eine Funktion dargestellt wird, müssen Sie keine Klammern nach dem Eigenschaftsnamen setzen, um diese Funktion aufzurufen. Das heißt, ein Design wie
accessorObj.name();
falsch.
Beim Versuch, auf die Eigenschaft
accessorObj.name
zuzugreifen,
accessorObj.name
beim Versuch, sie zu lesen, wird die entsprechende Funktion ausgeführt und der zurückgegebene Wert wird zum Wert der Eigenschaft
name
.
Die
get
Funktionen werden als Getter bezeichnet und sind für das Abrufen der Werte verantwortlich. Wenn wir unser Beispiel fortsetzen und versuchen, den Wert der
name
Eigenschaft des
accessorObj
Objekts zu ändern, indem wir beispielsweise den Befehl
accessorObj.name = 'New Person';
dann stellt sich heraus, dass nichts passieren wird. Der Punkt hier ist, dass die Setter-Funktion nicht mit der
name
verknüpft ist. Mit solchen Funktionen können Sie die Reihenfolge anpassen, in der den Eigenschaften von Objekten, deren Zugriff mithilfe von Gettern organisiert wird, neue Werte zugewiesen werden.
So sieht eine Objektdeklaration mit einem Getter und einem Setter aus:
const accessorObj = { _name: 'Arfat', get name() { return this._name; }, set name(value) { this._name = value; } };
Die Setter-Funktion empfängt, was sie versucht, der Eigenschaft des Objekts als Parameter zuzuweisen. Jetzt können Sie etwas in der Eigenschaft des Objekts speichern. In diesem Fall erstellen wir eine "private" Eigenschaft des
_name
Objekts. Das erste Zeichen des Namens einer solchen Eigenschaft ist ein Unterstrich, der nichts weiter als ein Hinweis für den Programmierer ist und angibt, dass diese Eigenschaft für die internen Anforderungen des Objekts bestimmt ist. Außerdem arbeiten wir damit, wenn wir auf die Eigenschaft des Namensobjekts zugreifen, auf die der Zugriff vom Getter und Setter geregelt wird.
Gleichzeitig können wir in der Getter-Funktion den Wert der Eigenschaft
_name
ändern, bevor wir ihn zurückgeben.
So könnte es aussehen:
const obj = { get name() { return this._name.toUpperCase(); }, set name(value) { this._name = value; }, get id() { return this._id.toString(2);
Dieses Programm enthält übrigens die Antwort auf eine der am Anfang des Artikels gestellten Fragen, die die Analyse von auf den ersten Blick unverständlichem Code betrifft.
Warum sollte jemand Eigenschaften mit Zugriffsmethoden benötigen, wenn Sie sicher mit normalen Eigenschaften arbeiten können? Sie können beispielsweise erforderlich sein, um Informationen zu Eigenschaftslesevorgängen zu protokollieren oder einen Verlauf von Änderungen an Eigenschaftswerten zu speichern. Eigenschaften mit Zugriffsmethoden bieten uns alle Möglichkeiten, Daten mithilfe von Funktionen zu verarbeiten, und die Einfachheit, mit gewöhnlichen Eigenschaften zu arbeiten. Lesen Sie hier mehr über die Verwendung solcher Eigenschaften.
Wie unterscheidet JavaScript zwischen gewöhnlichen Eigenschaften, in denen Daten gespeichert werden, von Eigenschaften mit Zugriffsmethoden? Finde das heraus.
Objekteigenschaftsbeschreibungen
Auf den ersten Blick scheint es eine direkte Entsprechung zwischen den Schlüsseln und den in Objekten gespeicherten Werten zu geben. Dies ist jedoch nicht ganz richtig.
▍ Eigenschaftsattribute
Jeder Schlüssel des Objekts ist einer Reihe von Attributen zugeordnet, die die Eigenschaften des diesem Schlüssel zugeordneten Werts bestimmen. Diese Attribute können auch als Metadaten betrachtet werden, die ein
:
Paar beschreiben.
Attribute werden verwendet, um den Status der Eigenschaften von Objekten festzulegen und zu beschreiben. Die Menge der Eigenschaftsattribute wird als Deskriptor bezeichnet. Es gibt sechs Eigenschaftsattribute:
[[Value]]
[[Get]]
[[Set]]
[[Writable]]
[[Enumerable]]
[[Configurable]]
Warum sind Eigenschaftsattributnamen in dieser Liste im Konstrukt
[[]]
? Doppelte Klammern zeigen an, dass dies Entitäten sind, die von den internen Mechanismen der Sprache verwendet werden. Ein JS-Programmierer kann nicht direkt auf diese Eigenschaften zugreifen. Um sie zu beeinflussen, werden geeignete Methoden angewendet.
Betrachten Sie das folgende Bild
von hier , auf dem Sie das Objekt und die Attribute seiner Eigenschaften sehen können.
Objekt und Attribute seiner EigenschaftenUnser Objekt hat 2 Schlüssel -
x
und
y
. Darüber hinaus ist jedem von ihnen eine Reihe von Attributen zugeordnet.
Wie können Sie mithilfe von JavaScript Informationen über das Objekt abrufen, ähnlich wie in der vorherigen Abbildung?
Object.getOwnPropertyDescriptor()
können Sie die Funktion
Object.getOwnPropertyDescriptor()
verwenden. Es nimmt ein Objekt und den Namen seiner Eigenschaft und gibt dann ein Objekt zurück, das die Attribute dieser Eigenschaft enthält. Hier ist ein Beispiel:
const object = { x: 5, y: 6 }; Object.getOwnPropertyDescriptor(object, 'x');
Es ist zu beachten, dass die Zusammensetzung der Attribute einer bestimmten Eigenschaft von ihrem Typ abhängt. Alle sechs Attribute derselben Eigenschaft werden nicht gefunden.
- Wenn es sich um Eigenschaften mit Daten handelt, haben sie nur die Attribute
[[Value]]
, [[Writable]]
, [[Enumerable]]
und [[Configurable]]
. - Eigenschaften mit Zugriffsmethoden haben anstelle der Attribute
[[Value]]
und [[Writable]]
Attribute [[Get]]
und [[Set]]
.
▍ [[Wert]]
Dieses Attribut speichert, was zurückgegeben wird, wenn versucht wird, den Eigenschaftswert eines Objekts abzurufen. Das heißt, wenn wir im vorherigen Beispiel eine Konstruktion des Formulars
object.x
, erhalten wir, was im Attribut
[[Value]]
gespeichert ist. Das gleiche passiert, wenn Sie versuchen, die Eigenschaften eines Objekts in eckigen Klammern zu lesen.
▍ [[Get]]
Dieses Attribut speichert einen Verweis auf eine Funktion, die eine Getter-Eigenschaft ist. Diese Funktion wird ohne Argumente aufgerufen, wenn versucht wird, den Wert einer Eigenschaft zu lesen.
▍ [[Einstellen]]
Hier wird der Link zu der Funktion gespeichert, die beim Erstellen der Setter-Eigenschaft deklariert wurde. Es wird mit einem Argument aufgerufen, das den Wert darstellt, den sie der Eigenschaft zuweisen wollten, dh es wird bei jeder Operation zum Zuweisen eines neuen Werts zu einer Eigenschaft aufgerufen.
const obj = { set x(val) { console.log(val)
In diesem Beispiel wird die rechte Seite des Ausdrucks als
val
Argument an die Setter-Funktion übergeben.
Hier ist der Code, der die Verwendung von Setzern und Gettern demonstriert.
▍ [[Beschreibbar]]
Dieses Attribut enthält einen booleschen Wert. Es gibt an, ob der Eigenschaftswert überschrieben werden kann oder nicht. Wenn hier
false
gespeichert ist, schlagen Versuche, den Wert der Eigenschaft zu ändern, fehl.
▍ [[Aufzählbar]]
Hier wird auch ein logischer Wert gespeichert. Dieses Attribut steuert die Ausgabe der Eigenschaft in
for-in
Schleifen. Wenn es auf
true
, ist es möglich, mit der Eigenschaft unter Verwendung solcher Zyklen zu arbeiten.
▍ [[Konfigurierbar]]
Dieses Attribut wird auch durch einen booleschen Wert dargestellt. Dies passiert, wenn
false
darin gespeichert ist:
- Die Eigenschaft kann nicht gelöscht werden.
- Sie können keine Eigenschaften, die Daten speichern, mit Zugriffsmethoden in Eigenschaften konvertieren und umgekehrt. Versuche, solche Transformationen durchzuführen, führen zu nichts.
- Es ist nicht zulässig, Eigenschaftsattributwerte zu ändern. Das heißt, die aktuellen Werte der Attribute
[[Enumerable]]
, [[Configurable]]
, [[Get]]
und [[Set]]
bleiben unverändert.
Die Auswirkung der Einstellung dieses Attributs auf
false
hängt auch von der Art der Eigenschaft ab. Dieses Attribut wirkt sich zusätzlich zu den oben genannten Auswirkungen auf Eigenschaften auf diese aus und so:
- Wenn dies eine Eigenschaft ist, in der Daten gespeichert werden, kann das Attribut
[[Writable]]
nur von true
in false
geändert werden. - Bis das Attribut
[[Writable]]
auf false
, kann das Attribut [[Value]]
geändert werden. Nachdem die Attribute [[Writable]]
und [[Configurable]]
auf " false
, stellt sich heraus, dass die Eigenschaft nicht beschreibbar, nicht löschbar und unveränderlich ist.
Arbeiten Sie mit Deskriptoren
Nachdem wir uns mit Attributen vertraut gemacht haben, werden wir uns fragen, wie wir sie beeinflussen können. JavaScript verfügt über spezielle Funktionen zum Arbeiten mit Eigenschaftsbeschreibungen. Reden wir über sie.
▍ Methode Object.getOwnPropertyDescriptor ()
Wir haben diese Methode bereits getroffen. Es nimmt ein Objekt und den Namen seiner Eigenschaft und gibt entweder
undefined
oder ein Objekt mit einem Eigenschaftsdeskriptor zurück.
▍ Methode Object.defineProperty ()
Dies ist eine statische
Object
, mit der Sie Objekten Eigenschaften hinzufügen oder vorhandene Eigenschaften ändern können. Es werden drei Argumente benötigt - ein Objekt, ein Eigenschaftsname und ein Objekt mit einem Deskriptor. Diese Methode gibt ein geändertes Objekt zurück. Betrachten Sie ein Beispiel:
const obj = {};
Es kann in Node.js ausgeführt werden. Der Code stellte sich als ziemlich groß heraus, aber tatsächlich ist er ziemlich einfach. Wir werden es analysieren und uns auf Kommentare der Form
// #n
.
In Fragment
#1
wir die Funktion
defineProperty
und übergeben ihr das Objekt
obj
, den Namen der
id
Eigenschaft und ein Deskriptorobjekt, das nur die Eigenschaft
value
enthält.
obj
, dass
42
in das Attribut
[[Value]]
wird. Denken Sie daran, dass Werte für Attribute wie
[[Enumerable]]
oder
[[Configurable]]
in diesem Objekt standardmäßig auf
false
werden. In diesem Fall werden die Attribute
[[Writable]]
,
[[Enumerable]]
und
[[Configurable]]
Eigenschaft
id
auf
false
.
An der als
#2
gekennzeichneten Stelle versuchen wir, eine Zeichenfolgendarstellung des Objekts in der Konsole anzuzeigen. Da die
id
Eigenschaft nicht aufzählbar ist, wird sie nicht angezeigt. Darüber hinaus existiert die Eigenschaft, was ihren erfolgreichen Abschluss durch Befehl
#3
beweist.
Beim Erstellen eines Objekts (Fragment
#4
) definieren wir eine vollständige Liste der Attribute. Setzen Sie insbesondere
[[Writable]]
auf
false
.
Mit den Befehlen
#5
und
#7
zeigen wir den Wert der Namenseigenschaft an. Aber zwischen ihnen (Fragment
#6
) haben wir versucht, diesen Wert zu ändern. Diese Operation hat den Wert der Eigenschaft nicht geändert, da das Attribut
[[Writable]]
auf
false
. Infolgedessen geben beide Befehle dasselbe an die Konsole aus.
Befehl
#8
ist ein Versuch, die Eigenschaft
id
zu entfernen. Denken Sie daran, dass das Attribut
[[Configurable]]
auf
false
, was bedeutet, dass es nicht gelöscht werden kann. Dies wird von Team
#9
bewiesen.
Fragment
#10
zeigt die Verwendung der Funktion
Object.defineProperties () . Es funktioniert genauso wie die Funktion
defineProperty()
, ermöglicht jedoch in einem Aufruf, mehrere Eigenschaften des Objekts zu beeinflussen, während
defineProperty()
nur mit einer Eigenschaft des Objekts arbeitet.
Objektschutz
Von Zeit zu Zeit muss der Entwickler Objekte vor Störungen von außen schützen. Angesichts der Flexibilität von JavaScript ist es beispielsweise sehr leicht, die Eigenschaften eines Objekts, das sich nicht ändern sollte, fälschlicherweise zu ändern. Es gibt drei Hauptmethoden zum Schutz von Objekten.
▍ Methode Object.preventExtensions ()
Die
Object.preventExtensions()
-Methode verhindert, dass das Objekt erweitert wird, dh neue Eigenschaften hinzugefügt werden. Es nimmt ein Objekt und macht es nicht erweiterbar. Beachten Sie, dass Sie Eigenschaften aus einem solchen Objekt entfernen können. Betrachten Sie ein Beispiel:
const obj = { id: 42 }; Object.preventExtensions(obj); obj.name = 'Arfat'; console.log(obj);
Um herauszufinden, ob ein Objekt nicht erweiterbar ist, können Sie die
Object.isExtensible()
-Methode verwenden. Wenn
true
, können Sie dem Objekt neue Eigenschaften hinzufügen.
▍ Methode Object.seal ()
Die Methode
seal()
scheint Objekte zu „versiegeln“. Hier ist, worüber wir sprechen:
- Seine Verwendung verhindert, dass dem Objekt neue Eigenschaften hinzugefügt werden (in diesem
Object.preventExtensions()
ähnelt es Object.preventExtensions()
). - Alle vorhandenen Eigenschaften eines Objekts können nicht konfiguriert werden.
- Werte vorhandener Eigenschaften können geändert werden, wenn ihr Attribut
[[Writable]]
nicht auf false
ist.
Infolgedessen stellt sich heraus, dass diese Methode das Hinzufügen neuer Eigenschaften zum Objekt und das Entfernen der darin vorhandenen Eigenschaften verhindert.
Betrachten Sie ein Beispiel:
const obj = { id: 42 }; Object.seal(obj); delete obj.id
Um zu überprüfen, ob das Objekt "versiegelt" ist oder nicht, können Sie die
Object.isSealed()
-Methode verwenden.
▍ Methode Object.freeze ()
Mit der Methode
freeze()
können Sie Objekte „einfrieren“ und sie mit dem höchstmöglichen Schutzniveau in JavaScript ausstatten. So funktioniert es:
- Versiegelt ein Objekt mit
Object.seal()
. - Verbietet die Änderung vorhandener Eigenschaften des Objekts vollständig.
- Verbietet das Ändern von Eigenschaftsbeschreibungen.
Hier ist ein Beispiel:
const obj = { id: 42 }; Object.freeze(obj); delete obj.id
Sie können das Objekt mithilfe der
Object.isFrozen()
-Methode überprüfen, ob es "eingefroren" ist.
▍ Übersicht über die Methoden zum Schutz von Objekten
Es ist wichtig zu beachten, dass die oben beschriebenen Methoden zum Schutz von Objekten nur deren Eigenschaften betreffen, die keine Objekte sind.
Hier ist eine Übersichtstabelle zu den betrachteten Methoden zum Schutz von Objekten, die hier entnommen wird.
| Eigenschaftserstellung
| Eigenschaftslesung
| Eigenschaft überschreiben
| Eigentumsentfernung
|
Object.freeze()
| - - | +
| - - | - - |
Object.seal()
| - - | +
| +
| - - |
Object.preventExtensions()
| - - | +
| +
| +
|
Zusammenfassung
Angesichts der Häufigkeit, mit der Objekte in JavaScript-Code verwendet werden, ist es für jeden Entwickler wichtig zu wissen, wie sie angeordnet sind. Wir hoffen, dass das, was Sie durch das Lesen dieses Materials gelernt haben, für Sie nützlich ist. Außerdem kennen Sie jetzt die Antworten auf die am Anfang des Artikels aufgeführten Fragen.
Liebe Leser! Wie schützen Sie JavaScript-Objekte?