ホームページ >ウェブフロントエンド >jsチュートリアル >JavaScriptのデザインパターン(継承)_JavaScriptスキルを学ぶ

JavaScriptのデザインパターン(継承)_JavaScriptスキルを学ぶ

WBOY
WBOYオリジナル
2016-05-16 15:29:391051ブラウズ

1. 継承

JavaScript の継承は非常に複雑なトピックであり、他のオブジェクト指向言語の継承よりもはるかに複雑です。他のほとんどのオブジェクト指向言語では、クラスからの継承にはキーワードの使用のみが必要です。これらとは異なり、JavaScript でパブリック メンバーを継承するという目的を達成するには、一連の対策を講じる必要があります。さらに、JavaScript はプロトタイプ継承を使用する数少ない言語の 1 つです。言語の柔軟性のおかげで、標準のクラスベースの継承またはより微妙なプロトタイプの継承のいずれかを使用できます。

2. 継承はなぜ必要ですか?

一般的に言えば、クラスを設計するときは、コードの繰り返しを減らし、オブジェクト間の結合を弱めるように努めたいと考えています。継承を使用すると、以前の設計原則のニーズが満たされます。このメカニズムを使用すると、既存のクラスに基づいて設計し、既存のメソッドを利用できるため、設計の変更が容易になります。特定の方法でクラス構造を出力する toString() メソッドを持つ複数のクラスが必要であるとします。 もちろん、 toString() メソッドを定義するコードをコピーして各クラスに貼り付けることができますが、これを行う場合は常に。このメソッドの動作方法を変更する必要がある場合は、すべてのクラスで同じ変更を繰り返す必要があります。一方、ToStringProvider クラスを提供し、それらのクラスにこのクラスを継承させる場合は、toString メソッドを 1 か所で宣言するだけで済みます。

あるクラスが別のクラスから継承すると、2 つのクラスの間に強い結合が生じる可能性があります。つまり、一方のクラスが他方のクラスの内部実装に依存することになります。ドーパント クラスを使用して他のクラスにメソッドを提供するなど、この問題を回避するのに役立ついくつかのテクニックについて説明します。

3. クラスベースの継承

以下のコードを見てください:

<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> 

出力結果:
チャン・サン、11 歳
Student が person を正常に統合し、そのコア コードが Student.prototype = new Person(); であることがわかります。次の図はその原理を示しています。 >

Student.prototype を new Person() にポイントし、新しい Person の _proto_ が Person Prototype をポイントすることで、継承全体が完了します。

しかし、このアプローチには問題があります:

問題 1: 親クラスに参照型変数がある場合、データが不整合になる 次に、型が配列である趣味属性を person に追加します。

<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> 

出力結果:


チャン・サン、11 歳、サッカー Li Si 、12 歳、サッカー、女の子

John Doe の趣味は女の子のみであることがわかりますが、上記のコードにより、すべてのオブジェクトが趣味属性を共有できます。
上記の継承方法にはまだ問題があります:

質問 2: Student のコンストラクターでは、オブジェクトの作成と名前の初期化に new Student("00001", "Zhang San", 12) を使用できません。 age 属性には stu.name、stu.age を割り当てる必要があります。

上記の問題を解決するには、上記のコードを変更します:

<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> 

出力:


0001、張三、サッカー 0002、リー・シー、カンジン、バスケットボール

Student コンストラクターで Person.call(this,name,age) を使用すると、super(name,age) [呼び出しの最初のパラメーターはコンテキスト] のように感じられ、属性共有の問題が正常に解決されます。完璧に解決されています。

4. プロトタイプチェーンに基づく継承

<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> 

出力:


zhangsan、12、ジャワ lisi、13、Java、Javascript

参照属性が一貫していないという問題もあり、操作全体がオブジェクトに基づいているため、人々に良い印象を与えないことがわかります。その原理を以下に図で説明します。

オブジェクトはクローン関数を通じて継続的に新しいオブジェクトを返し、プロトタイプは受け取ったオブジェクトを実行します。継承プロセス全体は、実際には常に _proto_ を指してチェーンを形成しているため、プロトタイプ チェーンと呼ばれます。

JS の 2 つの統合方法のうち、最も安定しているのはクラス継承による方法です。

上記は、継承に関する関連知識のポイントを紹介したものであり、皆様の学習に役立つことを願っています。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。