Heim  >  Artikel  >  Web-Frontend  >  Erlernen Sie JavaScript-Entwurfsmuster (Kapselung)_Javascript-Kenntnisse

Erlernen Sie JavaScript-Entwurfsmuster (Kapselung)_Javascript-Kenntnisse

WBOY
WBOYOriginal
2016-05-16 15:29:421006Durchsuche

In JavaScript gibt es keine Unterstützung für abstrakte Klassen und Schnittstellen. Auch JavaScript selbst ist eine schwach typisierte Sprache. JavaScript kann oder muss nicht viel mehr tun, wenn es um die Kapselung von Typen geht. Für die Implementierung von Entwurfsmustern in JavaScript ist die Nichtunterscheidung von Typen eine Schande und kann auch als Erleichterung bezeichnet werden.

Aus der Perspektive der Designmuster spiegelt sich die Verpackung in Verpackungsänderungen auf einer wichtigeren Ebene wider.

Durch die Kapselung von Änderungen isolieren wir die stabilen Teile des Systems von den Teilen, die sich leicht ändern lassen. Während der Entwicklung des Systems müssen wir nur die Teile ersetzen, die leicht zu ändern sind Ja, es ist relativ einfach auszutauschen. Dadurch kann die Stabilität und Skalierbarkeit des Programms weitestgehend gewährleistet werden.

Es gibt drei grundlegende Modi der JavaScript-Kapselung:

1. Verwenden Sie das Prinzip der Vereinbarungspriorität und alle privaten Variablen beginnen mit _

 <script type="text/javascript">
  /**
   * 使用约定优先的原则,把所有的私有变量都使用_开头
   */
  var Person = function (no, name, age)
  {
   this.setNo(no);
   this.setName(name);
   this.setAge(age);
  }
  Person.prototype = {
   constructor: Person,
   checkNo: function (no)
   {
    if (!no.constructor == "string" || no.length != 4)
     throw new Error("学号必须为4位");
   },
   setNo: function (no)
   {
    this.checkNo(no);
    this._no = no;
   }, 
   getNo: function ()
   {
    return this._no;
   setName: function (name)
   {
    this._name = name;
   }, 
   getName: function ()
   {
    return this._name;
   }, 
   setAge: function (age)
   {
    this._age = age;
   }, 
   getAge: function ()
   {
    return this._age;
   }, 
   toString: function ()
   {
    return "no = " + this._no + " , name = " + this._name + " , age = " + this._age;
   }
  };
  var p1 = new Person("0001", "小平果", "22");
  console.log(p1.toString());  //no = 0001 , name = 小平果 , age = 22
  p1.setNo("0003");
  console.log(p1.toString());  //no = 0003 , name = 小平果 , age = 22
  p1.no = "0004";
  p1._no = "0004";
  console.log(p1.toString()); //no = 0004 , name =小平果 , age = 22

 </script>

Haben Sie nach dem Lesen des Codes das Gefühl, betrogen worden zu sein? Wenn Sie einfach alle Variablen eingeben, die mit _ beginnen, kann dies natürlich als Kapselung bezeichnet werden hat Vorrang.

Bei dieser Verwendung des Unterstrichs handelt es sich um eine bekannte Namenskonvention, die darauf hinweist, dass eine Eigenschaft nur für die interne Verwendung des Objekts bestimmt ist und der Zugriff oder die direkte Festlegung darauf zu unerwarteten Konsequenzen führen kann. Dies trägt dazu bei, zu verhindern, dass Programmierer es versehentlich verwenden, es verhindert jedoch nicht, dass es absichtlich verwendet wird.

Diese Methode ist immer noch gut. Zumindest sind die Getter- und Setter-Methoden im Prototyp enthalten, nicht im Objekt. Insgesamt ist es eine gute Wahl. Wenn Sie der Meinung sind, dass dies nicht möglich ist und die Kapselung strikt implementiert werden muss, schauen Sie sich die zweite Methode an.

2. Implementieren Sie die Kapselung strikt

<script type="text/javascript">
  /**
   * 使用这种方式虽然可以严格实现封装,但是带来的问题是get和set方法都不能存储在prototype中,都是存储在对象中的
   * 这样无形中就增加了开销
   */
  var Person = function (no, name, age)
  {
   var _no , _name, _age ;
   var checkNo = function (no)
   {
    if (!no.constructor == "string" || no.length != 4)
     throw new Error("学号必须为4位");
   };
   this.setNo = function (no)
   {
    checkNo(no);
    _no = no;
   };
   this.getNo = function ()
   {
    return _no;
   }
   this.setName = function (name)
   {
    _name = name;
   }

   this.getName = function ()
   {
    return _name;
   }

   this.setAge = function (age)
   {
    _age = age;
   }
   this.
     getAge = function ()
   {
    return _age;
   }

   this.setNo(no);
   this.setName(name);
   this.setAge(age);
  }
  Person.prototype = {
   constructor: Person,
   toString: function ()
   {
    return "no = " + this.getNo() + " , name = " + this.getName() + " , age = " + this.getAge();
   }
  }
  ;
  var p1 = new Person("0001", "小平果", "22");
  console.log(p1.toString());  //no = 0001 , name =小平果 , age = 22
  p1.setNo("0003");
  console.log(p1.toString());  //no = 0003 , name = 小平果 , age = 22
  p1.no = "0004";
  console.log(p1.toString()); //no = 0003 , name = 小平果 , age = 22

 </script>

Wie unterscheidet sich dies von anderen Modi zum Erstellen von Objekten, über die wir zuvor gesprochen haben? Im obigen Beispiel verwenden wir immer das Schlüsselwort this, wenn wir die Eigenschaften eines Objekts erstellen und referenzieren. In diesem Beispiel deklarieren wir diese Variablen mit var. Dies bedeutet, dass sie nur im Person-Konstruktor vorhanden sind. Die checkno-Funktion wird auf die gleiche Weise deklariert und wird daher zu einer privaten Methode.

Methoden, die auf diese Variablen und Funktionen zugreifen müssen, müssen nur in Person deklariert werden. Diese Methoden werden als privilegierte Methoden bezeichnet, da sie öffentlich sind, aber Zugriff auf private Eigenschaften und Methoden haben. Um von außerhalb des Objekts auf diese privilegierten Funktionen zugreifen zu können, wird ihnen das Schlüsselwort this vorangestellt. Da diese Methoden im Bereich des Person-Konstruktors definiert werden, haben sie Zugriff auf private Eigenschaften. Auf diese Eigenschaften wird ohne Verwendung des Schlüsselworts this verwiesen, da sie nicht öffentlich sind. Alle Getter- und Zuweisungsmethoden wurden so geändert, dass sie ohne dies direkt auf diese Eigenschaften verweisen.

Jede Methode, die keinen direkten Zugriff auf private Eigenschaften erfordert, kann wie ursprünglich in Person.prototype deklariert werden. Wie die toString()-Methode. Nur Methoden, die direkten Zugriff auf private Mitglieder erfordern, sollten als privilegierte Methoden konzipiert werden. Aber zu viele privilegierte Methoden beanspruchen zu viel Speicher, da jede Objektinstanz eine neue Kopie aller privilegierten Methoden enthält.

Sehen Sie sich den obigen Code an, der Attributname wurde entfernt und die Kapselung wurde nur über Getter und Setter implementiert. Es gibt jedoch ein Problem. was den Speicheraufwand erhöht.

3. Eingekapselt in einem Verschluss

<script type="text/javascript">

  var Person = (function ()
  {
   //静态方法(共享方法)
   var checkNo = function (no)
   {
    if (!no.constructor == "string" || no.length != 4)
     throw new Error("学号必须为4位");
   };
   //静态变量(共享变量)
   var times = 0;

    //return the constructor.
   return function (no, name, age)
   {
    console.log(times++); // 0 ,1 , 2
    var no , name , age; //私有变量
    this.setNo = function (no) //私有方法
    {
     checkNo(no);
     this._no = no;
    };
    this.getNo = function ()
    {
     return this._no;
    }
    this.setName = function (name)
    {
     this._name = name;
    }

    this.getName = function ()
    {
     return this._name;
    }

    this.setAge = function (age)
    {
     this._age = age;
    }
    this.getAge = function ()
    {
     return this._age;
    }

    this.setNo(no);
    this.setName(name);
    this.setAge(age);
   }
  })();

  Person.prototype = {
   constructor: Person,
   toString: function ()
   {
    return "no = " + this._no + " , name = " + this._name + " , age = " + this._age;
   }
  };

  var p1 = new Person("0001", "小平果", "22");
  var p2 = new Person("0002", "abc", "23");
  var p3 = new Person("0003", "aobama", "24");


  console.log(p1.toString());  //no = 0001 , name = 小平果 , age = 22
  console.log(p2.toString());  //no = 0002 , name = abc , age = 23
  console.log(p3.toString()); //no = 0003 , name = aobama , age = 24

 </script>

Der obige Code führt nach dem Laden der JS-Engine direkt die Funktion „Person = sofortige Ausführung“ aus, und diese Funktion gibt dann eine Unterfunktion zurück, bei der es sich um den Konstruktor handelt, der von der neuen Person aufgerufen wird, und weil die Unterfunktion verwaltet wird Ein Verweis auf checkNo(no) und times in der Funktion zur sofortigen Ausführung (offensichtlicher Abschluss), sodass checkNo und times allen Person-Objekten gemeinsam sind. Nach dem Erstellen von drei Objekten sind die Zeiten 0, 1 bzw. 2. Der Vorteil dieses Ansatzes besteht darin, dass die Methoden und Eigenschaften, die in Person wiederverwendet werden müssen, privat gemacht und von Objekten gemeinsam genutzt werden können.

Die privaten Mitglieder und privilegierten Mitglieder werden hier weiterhin im Konstruktor deklariert. Der Konstruktor hat sich jedoch von einer gewöhnlichen Funktion in eine Inline-Funktion geändert und wird der Variablen Person als Rückgabewert der Funktion übergeben, die sie enthält. Dadurch wird ein Abschluss erstellt, in dem Sie statische private Mitglieder deklarieren können. Das Paar leerer Klammern nach der äußeren Funktionsdeklaration ist sehr wichtig. Seine Funktion besteht darin, die Funktion auszuführen, sobald der Code geladen wird. Der Rückgabewert dieser Funktion ist eine andere Funktion, die der Variablen Person zugewiesen wird, sodass Person zum Konstruktor wird. Diese innere Funktion wird beim Instanziieren von Person aufgerufen. Die äußere Funktion wird lediglich zum Erstellen eines Abschlusses verwendet, der zum Speichern statischer Elemente verwendet werden kann.

In diesem Beispiel ist checkno als statische Methode konzipiert, da es keinen Sinn macht, für jede Instanz von Person eine neue Kopie dieser Methode zu generieren. Es gibt auch ein statisches Attribut times, dessen Funktion darin besteht, die Gesamtzahl der Aufrufe des Person-Konstruktors zu verfolgen.

Das Obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, er wird für das Studium aller hilfreich sein. Sie können mehr über die Bedeutung der Kapselung erfahren.

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn