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

Erlernen Sie JavaScript-Entwurfsmuster (Vererbung)_Javascript-Kenntnisse

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

1. Vererbung

Vererbung in JavaScript ist ein sehr komplexes Thema, viel komplexer als die Vererbung in jeder anderen objektorientierten Sprache. In den meisten anderen objektorientierten Sprachen erfordert das Erben von einer Klasse lediglich die Verwendung eines Schlüsselworts. Im Gegensatz zu ihnen müssen eine Reihe von Maßnahmen ergriffen werden, um den Zweck der Vererbung öffentlicher Mitglieder in JavaScript zu erreichen. Darüber hinaus ist JavaScript eine der wenigen Sprachen, die prototypische Vererbung nutzt. Dank der Flexibilität der Sprache können Sie entweder die standardmäßige klassenbasierte Vererbung oder die subtilere prototypische Vererbung verwenden.

2. Warum ist eine Vererbung erforderlich?

Im Allgemeinen hoffen wir beim Entwerfen von Klassen, sich wiederholenden Code zu reduzieren und zu versuchen, die Kopplung zwischen Objekten zu schwächen. Die Verwendung der Vererbung erfüllt die Anforderungen des vorherigen Entwurfsprinzips. Mit diesem Mechanismus können Sie auf der Grundlage vorhandener Klassen entwerfen und die bereits vorhandenen Methoden nutzen, und es ist einfacher, den Entwurf zu ändern. Angenommen, Sie benötigen mehrere Klassen, um eine toString()-Methode zu haben, die die Klassenstruktur auf eine bestimmte Weise ausgibt. Natürlich können Sie den Code, der die toString()-Methode definiert, in jede Klasse kopieren und einfügen, aber wenn Sie dies tun, wann immer Wenn Sie die Funktionsweise dieser Methode ändern müssen, müssen Sie die gleiche Änderung in jeder Klasse wiederholen. Wenn Sie andererseits eine ToStringProvider-Klasse bereitstellen und diese Klassen dann diese Klasse erben lassen, muss die toString-Methode nur an einer Stelle deklariert werden.

Wenn eine Klasse von einer anderen Klasse erbt, kann dies zu einer starken Kopplung zwischen den beiden führen, das heißt, eine Klasse hängt von der internen Implementierung der anderen Klasse ab. Wir werden einige Techniken besprechen, die helfen können, dieses Problem zu vermeiden, einschließlich der Verwendung von Dotierstoffklassen, um Methoden für andere Klassen bereitzustellen.

3. Klassenbasierte Vererbung

Sehen Sie sich den folgenden Code an:

<script type="text/javascript"> 


  function Person(name, age) 
  { 
   this.name = name; 
   this.age = age; 
  } 
  Person.prototype.say = function () 
  { 
   console.log(this.name + " , " + this.age); 
  } 
  function Student(no) 
  { 
   this.no = no; 
  } 
  /** 
   * Student的prototype指向Person的对象 
   */</span> 
  Student.prototype = new Person(); 
  var stu1 = new Student("0001"); 
  stu1.name = '张三'; 
  stu1.age = '11'; 
  console.log(stu1.no); 
  stu1.say(); 
 </script> 

Ausgabeergebnis:
Zhang San, 11
Sie können sehen, dass Student Person erfolgreich integriert hat und über die Say-Methode von Person verfügt. Der Kerncode lautet tatsächlich Student.prototype = new Person();. Das Folgende ist ein Diagramm, um das Prinzip zu veranschaulichen >

Zeigen Sie Student.prototype auf new Person(), und das _proto_ der neuen Person zeigt auf Person Prototype. Damit ist die gesamte Vererbung abgeschlossen.

Aber es gibt Probleme mit diesem Ansatz:

Problem 1: Wenn die übergeordnete Klasse eine Referenztypvariable hat, sind die Daten inkonsistent. Als nächstes fügen wir ein Hobbys-Attribut zu Person hinzu, dessen Typ ein Array ist.

<script type="text/javascript"> 
  /** 
  * 存在问题 
  * 1、无法在Student的构造方法中传递参数用于父类的构造方法 
  * 2、对于引用类型变量,造成数据不一致 
  */ 


  function Person(name, age) 
  { 
   this.name = name; 
   this.age = age; 
   this.hobbies = [] ; 
  } 
  Person.prototype.say = function () 
  { 
   console.log(this.name + " , " + this.age +" , " +this.hobbies); 
  } 
  function Student(no) 
  { 
   this.no = no; 
  } 
  Student.prototype = new Person(); 

  var stu1 = new Student("0001"); 
  stu1.name = '张三'; 
  stu1.age = '11'; 
  stu1.hobbies.push("soccer"); 
  stu1.say(); 

  var stu2 = new Student("0002"); 
  stu2.name = '李四'; 
  stu2.age = '12'; 
  stu2.hobbies.push("girl"); 
  stu2.say(); 
 </script> 

Ausgabeergebnis:


Zhang San, 11, Fußball Li Si, 12, Fußball, Mädchen

Es ist ersichtlich, dass John Does Hobbys nur Mädchen sein sollten, aber der obige Code ermöglicht es allen Objekten, das Hobbys-Attribut zu teilen.
Es besteht immer noch ein Problem mit der oben genannten Vererbungsmethode:

Frage 2: Im Konstruktor von Student kann new Student("00001", "Zhang San", 12) nicht zum Erstellen eines Objekts und zum Initialisieren von Namen und verwendet werden age Attribute müssen stu.name, stu.age zugewiesen werden

Um das obige Problem zu lösen, ändern Sie den obigen Code:

<script type="text/javascript"> 

  function Person(name, age) 
  { 
   this.name = name; 
   this.age = age; 
   this.hobbies = []; 
  } 
  Person.prototype.say = function () 
  { 
   console.log(this.name + " , " + this.age +" , " + this.hobbies); 
  } 

  function Student(name, age, no) 
  { 
   /** 
   * 使用call方法,第一个参数为上下文; 
   * 有点类似Java中的super(name,age)的感觉 
   */ 
   Person.call(this, name, age); 
   this.no = no; 
  } 

  Student.prototype = new Person(); 

  var stu1 = new Student("0001","张三",11); 
  stu1.hobbies.push("soccer"); 
  stu1.say(); 

  var stu2 = new Student("0002","李四",12); 
  stu2.hobbies.push("cangjin"); 
  stu2.hobbies.push("basketball"); 
  stu2.say(); 
 </script> 

Ausgabe:


0001, Zhang San, Fußball 0002, Li Si, Cangjin, Basketball

Die Verwendung von Person.call(this,name,age) im Student-Konstruktor fühlt sich an wie super(name,age) [der erste Parameter des Aufrufs ist der Kontext] und löst erfolgreich das Referenzproblem der Attributfreigabe ist perfekt gelöst.

4. Vererbung basierend auf der Prototypenkette

<script type="text/javascript"> 

 /** 
  * 基于原型链的集成中都是对象 
  * 存在问题: 
  * 1、对于引用类型变量,造成数据不一致 
  */ 
 var Person = { 
    name: "人", 
    age: 0, 
    hobbies: [], 
    say: function () 
    { 
     console.log(this.name + " , " + this.age + " , " + this.hobbies); 
    } 
   } 
   ; 

 var Student = clone(Person); 
 Student.no =""; 
 Student.sayHello = function() 
 { 
  console.log(this.name +"hello ") ; 
 } 

 var stu1 = clone(Student); 
 stu1.name = "zhangsan"; 
 stu1.age = 12; 
 stu1.hobbies.push("Java"); 
 stu1.say(); 

 var stu2 = clone(Student); 
 stu2.name = "lisi"; 
 stu2.age = 13; 
 stu2.hobbies.push("Javascript"); 
 stu2.say(); 

 /** 
  * 返回一个prototype执行obj的一个对象 
  * @param obj 
  * @returns {F} 
  */ 
 function clone(obj) 
 { 
  var F = function () 
  { 
  }; 
  F.prototype = obj; 
  return new F(); 

 } 
</script> 

Ausgabe:


zhangsan, 12, Java lisi, 13, Java,Javascript

Es ist ersichtlich, dass es auch das Problem inkonsistenter Referenzattribute gibt und die gesamte Operation auf Objekten basiert, was den Menschen kein gutes Gefühl gibt. Das Prinzip wird unten anhand von Diagrammen erläutert:

Objekte geben über eine Klonfunktion kontinuierlich ein neues Objekt zurück, und der Prototyp führt das eingehende Objekt aus. Der gesamte Vererbungsprozess weist tatsächlich ständig darauf hin, eine Kette zu bilden, daher wird er als Prototypkette bezeichnet.

Okay, wir haben es eingeführt. Die beste von den beiden Integrationsmethoden ist die Klassenvererbung, die relativ stabil ist.

Das Obige ist eine Einführung in die relevanten Wissenspunkte zum Thema Vererbung. Ich hoffe, es wird für das Lernen aller hilfreich sein.

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