Kapselung in JavaScript

Dies wird heute mein letzter Beitrag in der Reihe „JavaScript für (C /) AL-Entwickler“ sein. Wenn ich weiterhin über fast reines JavaScript-Zeug bloggen würde, könnte man vernünftigerweise fragen, ob dies tatsächlich ein NAV-Blog oder ein JavaScript-Blog ist. Es ist immer noch da, und während das, worüber ich schreiben werde, ein reines JavaScript-Konzept ist, finde ich es für jeden Steuerelement-Add-In-Entwickler sehr relevant. Also, halt mein Bier und ertrage es mit mir für ein anderes.

Eine der Beschwerden, die ich oft über JavaScript höre, ist, dass es in JavaScript keine Kapselung gibt. Dies ist fast vollständig wahr, abgesehen von der Tatsache, dass es völlig falsch ist.

Wo ist das Problem an erster Stelle, und was ist dann die Lösung? Lass uns eintauchen.

Das Problem

Stellen Sie sich vor, Sie deklarieren einen Konstruktor. Stellen Sie sich für eine Sekunde vor, wir befinden uns in der ES5-Welt (die wir leider verwenden müssen, wenn unsere Steuerungs-Add-Ins vollständig mit allen Plattformen kompatibel sein sollen, auf denen sowohl NAV als auch Business Central unterstützt werden).

Das ist mein Code:

Offensichtlich, Dies zeigt 42, Das ist mein aktuelles Alter.

Bald wird es mein Geburtstag sein, also würde dies zeigen 43:

Jetzt, während ich absolut gerne in der Lage wäre, so etwas im wirklichen Leben zu tun:

… das wird nicht passieren. In einer anständigen objektorientierten Welt sollte „age“ eine gekapselte Eigenschaft sein, und Sie sollten vjeko nicht aufrufen können.alter = 25 überhaupt. C # und „normale“ objektorientierte Sprachen haben ein Konzept der Kapselung, sie können dies mit privaten Feldern handhaben, aber JavaScript hat kein Konzept von privat. Alles, was im Objektkonstruktor (oder später in einer Instanz eines konstruierten Objekts) definiert ist, ist für den gesamten Code, der Zugriff auf diese Instanz hat, vollständig zugänglich. In meinem obigen Beispiel kann jeder das Alter festlegen und damit durchkommen.

Man könnte sagen, dass JavaScript keine Kapselung hat. Und wie ich oben sagte, Sie wären völlig falsch.

Die Lösung

So offensichtlich es auch ist, dass wir nichts direkt als privat deklarieren können, es gibt immer noch Dinge, die wir verwenden können. Ein schönes Konzept, das nützlich ist, heißt Closures. Verschlüsse werden ausführlich in einer Million Blogs, Dokumentationsseiten und Codebeispielen im gesamten Internet erklärt, und Sie können die Bejesus in Ihrem eigenen Tempo googeln, sodass ich mich hier nicht mit der Erklärung von Verschlüssen befassen werde. Ich werde sie einfach direkt anwenden, um das Kapselungsproblem zu lösen.

Es gibt mindestens zwei Möglichkeiten, wie Sie damit umgehen können. Lassen Sie uns zuerst das offensichtlichere tun: eine Zugriffsfunktion.

Stellen Sie sich die Welt ohne Eigenschaften vor, in der Sie kein Objekt ausführen können.eigenschaft = Wert (wie vjeko.alter = 25 in unserem Fall, so sehr ich es total lieben würde!). In dieser Welt hätten Sie Getter- und Setter-Funktionen:

( ignoriere für einen Moment die Tatsache, dass ich das immer noch benutze.(um die „Eigenschaft“ zu „kapseln“)

Offensichtlich könnten Sie diese folgendermaßen aufrufen:

Wenn Sie age dann schreibgeschützt haben möchten, löschen Sie einfach die SETAG-Setter-Funktion. Wenn das.das Alter war wirklich privat (was es nicht ist), das würde den Trick für dich tun. Das Problem ist, nichts, was darin definiert ist, ist privat, es ist für jeden zugänglich, der Zugriff auf eine Instanz des Objekts hat. Es ist so öffentlich wie es nur geht.

Um dieses Problem zu beheben, müssen wir zunächst die Getter-Funktionsdeklaration vom Prototyp in die Instanz verschieben. Prototype-Mitglieder kommen dem am nächsten, was wir in C # als statisch bezeichnen würden, obwohl sie zur Laufzeit bestimmte Verhaltensmerkmale sowohl von statischen als auch von Instanzmitgliedern aufweisen. Lassen Sie uns jedoch zuerst das Element vom Prototyp weg und auf die Instanz verschieben:

Dies löst nur den ersten Teil des Problems, die Tatsache, dass getAge eher für den Prototyp als für die Instanz definiert wurde. Mit einer einfachen Änderung wie dieser:

… wir lösen das Problem vollständig:

Das Alter ist jetzt vollständig eingekapselt. Sie können über die Getter-Funktion darauf zugreifen, sie können es jedoch nicht direkt festlegen, da nur im closure-Bereich von this darauf zugegriffen werden kann.getAge Instanz-Funktion.

Um die Person-Klasse vollständig zu implementieren, müssen Sie die growOlder-Funktion vom Prototyp in die Instanz verschieben:

Und das funktioniert genau so, wie Sie es möchten:

Aber warum funktioniert es? Es funktioniert wegen Schließungen. Der Altersparameter aus dem Konstruktor wurde im Abschlussbereich der Funktionen getAge und growOlder erfasst, sodass Sie von beiden Funktionen aus auf seinen Wert zugreifen können, aber für andere Personen an anderer Stelle völlig unzugänglich sind.

Noch bessere Lösung

Sie könnten sagen, dass Sie nicht über eine Getter-Funktion darauf zugreifen möchten und dass Sie eine vollständige schreibgeschützte Eigenschaftssyntax benötigen. Sie möchten, dass Ihr Alter schreibgeschützt und gleichzeitig gekapselt ist. Hab dich! JavaScript kann das nicht kapseln! Außer dass es absolut kann.

Ich habe das Objekt angesprochen.defineProperty Methode in meinem vorherigen Beitrag, und wenn Sie das lesen, können Sie sofort sehen, wie es hier angewendet werden kann.

Definieren wir also eine schreibgeschützte Instanzeigenschaft der Person-Klasse:

Dort. Es tat nicht weh. Und es funktioniert:

Da hast du es also. Vollständige Kapselung in JavaScript, damit Sie guten, isolierten Code schreiben und Ihre Steuerungs-Add-Ins auf ein echtes Kick-a $$ -Niveau bringen können.

Happy JavaScripting, und ich hoffe, mehr Zeit zu haben, um über andere coole und nützliche JavaScript-Tipps und Tricks für (C /) AL-Entwickler zu bloggen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.