ホームページ ウェブフロントエンド jsチュートリアル JavaScript継承の基礎(プロトタイプチェーン、借用コンストラクター、混合モード、プロトタイプ継承、寄生継承、寄生複合継承)_JavaScriptスキル

JavaScript継承の基礎(プロトタイプチェーン、借用コンストラクター、混合モード、プロトタイプ継承、寄生継承、寄生複合継承)_JavaScriptスキル

May 16, 2016 pm 04:39 PM
継承する

JavaScript の継承について説明すると約束していましたが、今のところ遅れています。早速、本題に入りましょう。

継承を理解したいということは、オブジェクト指向 JavaScript をある程度理解していることを意味します。まだ理解できない場合は、「オブジェクト指向 JS の基本的な説明」を参照してください。ファクトリモード、コンストラクターモード、プロトタイプモード、混合モード、動的プロトタイプモード》、JavaScriptの継承を完了するために一般的に使用されるメソッドについて話しましょう。

プロトタイプチェーン

JavaScript で継承を実装する最も簡単な方法は、プロトタイプ チェーンを使用することです。つまり、「subtype.prototype = newparent type ();」というように、サブタイプのプロトタイプを親タイプのインスタンスにポイントします。実装方法は以下の通りです:

// 为父类型创建构造函数
function SuperType() {
  this.name = ['wuyuchang', 'Jack', 'Tim'];
  this.property = true;
}

// 为父类型添加方法
SuperType.prototype.getSuerperValue = function() {
  return this.property;
}

// 为子类型创建构造函数
function SubType() {
  this.test = ['h1', 'h2', 'h3', 'h4'];
  this.subproperty = false;
}

// 实现继承的关键步骤,子类型的原型指向父类型的实例
SubType.prototype = new SuperType();

// 在此处给子类型添加方法,一定要在实现继承之后,否则会在将指针指向父类型的实例,则方法为空
SubType.prototype.getSubValue = function() {
  return this.subproperty;
}


/* 以下为测试代码示例 */
var instance1 = new SubType();
instance1.name.push('wyc');
instance1.test.push('h5');
alert(instance1.getSuerperValue());    // true
alert(instance1.getSubValue());      // false
alert(instance1.name);          // wuyuchang,Jack,Tim,wyc
alert(instance1.test);          // h1,h2,h3,h4,h5


var instance2 = new SubType();
alert(instance2.name);          // wuyuchang,Jack,Tim,wyc
alert(instance2.test);          // h1,h2,h3,h4
ログイン後にコピー

上記のコードはプロトタイプ チェーンを通じて実装された単純な継承であることがわかりますが、テスト コードの例にはまだいくつかの問題があります。私のブログ記事「オブジェクト指向JS、ファクトリモード、コンストラクタモード、プロトタイプモード、ハイブリッドモード、ダイナミックプロトタイプモードの基本解説」を読んだ子供たちは、プロトタイプチェーンコードの存在を知っているはずです最初の問題は、サブタイプのプロトタイプが親タイプのインスタンス、つまり、サブタイプのプロトタイプに含まれる親タイプの属性であるため、参照型値のプロトタイプ属性がすべてのインスタンス によって共有されます。上記のコードのinstance1.name.push('wyc'); は、この問題の存在を証明できます。プロトタイプ チェーンの 2 番目の問題は次のとおりです。 サブタイプのインスタンスを作成するとき、パラメーター をスーパータイプのコンストラクターに渡すことができません。したがって、実際の開発ではプロトタイプチェーンのみを使用することはほとんどありません。

コンストラクターを借用

プロトタイプ チェーンに存在する 2 つの問題を解決するために、開発者は借用コンストラクターと呼ばれる手法を使用してプロトタイプ チェーンに存在する問題を解決し始めました。このテクノロジーの実装アイデアも非常にシンプルで、サブタイプのコンストラクター内で親タイプのコンストラクターを呼び出すだけです。関数は特定の環境でコードを実行する単なるオブジェクトであるため、apply() メソッドまたは call() メソッドを介して コンストラクター を実行できることを忘れないでください。コードは次のとおりです:

// 为父类型创建构造函数
function SuperType(name) {
  this.name = name;
  this.color = ['pink', 'yellow'];
  this.property = true;

  this.testFun = function() {
    alert('http://tools.jb51.net/');
  }
}

// 为父类型添加方法
SuperType.prototype.getSuerperValue = function() {
  return this.property;
}

// 为子类型创建构造函数
function SubType(name) {
  SuperType.call(this, name);
  this.test = ['h1', 'h2', 'h3', 'h4'];
  this.subproperty = false;
}

// 在此处给子类型添加方法,一定要在实现继承之后,否则会在将指针指向父类型的实例,则方法为空
SubType.prototype.getSubValue = function() {
  return this.subproperty;
}


/* 以下为测试代码示例 */
var instance1 = new SubType(['wuyuchang', 'Jack', 'Nick']);
instance1.name.push('hello');
instance1.test.push('h5');
instance1.color.push('blue');
instance1.testFun();            // http://tools.jb51.net/
alert(instance1.name);            // wuyuchang,Jack,Nick,hello
// alert(instance1.getSuerperValue());    // error 报错
alert(instance1.test);            // h1,h2,h3,h4,h5    
alert(instance1.getSubValue());        // false    
alert(instance1.color);            // pink,yellow,blue

var instance2 = new SubType('wyc');
instance2.testFun();            // http://tools.jb51.net/
alert(instance2.name);            // wyc    
// alert(instance2.getSuerperValue());    // error 报错
alert(instance2.test);            // h1,h2,h3,h4
alert(instance2.getSubValue());        // false
alert(instance2.color);            // pink,yellow
ログイン後にコピー

上記のコードでは、サブタイプ SubType のコンストラクターがスーパータイプ「SuperType.call(this, name);」を呼び出していることがわかり、作成時にプロパティの継承を実現することもできます。サブタイプのインスタンスが渡されますが、新たな問題が再び発生します。親型のコンストラクターにメソッド testFun を定義し、親型のプロトタイプにメソッド getSuperValue を定義していることがわかります。ただし、 がサブタイプをインスタンス化した後でも、親型のプロトタイプに定義されているメソッド getSuperValue を呼び出すことはできません。親型のコンストラクター メソッド testFun のみを呼び出すことができます。 。これは、オブジェクトの作成時にコンストラクター パターンのみを使用するのと同じであり、関数が再利用できなくなります。これらの問題を考慮すると、コンストラクターを借用する手法が単独で使用されることはほとんどありません。

結合継承 (プロトタイプチェーン借用コンストラクター)

名前が示すように、結合継承は、プロトタイプ チェーンの使用とコンストラクターの借用の利点を組み合わせたパターンです。実装も非常に簡単です。組み合わせであるため、プロトタイプチェーン継承メソッド とコンストラクター継承属性 の両方の利点を確実に組み合わせています。具体的なコードの実装は次のとおりです:

// 为父类型创建构造函数
function SuperType(name) {
  this.name = name;
  this.color = ['pink', 'yellow'];
  this.property = true;

  this.testFun = function() {
    alert('http://tools.jb51.net/');
  }
}

// 为父类型添加方法
SuperType.prototype.getSuerperValue = function() {
  return this.property;
}

// 为子类型创建构造函数
function SubType(name) {
  SuperType.call(this, name);
  this.test = ['h1', 'h2', 'h3', 'h4'];
  this.subproperty = false;
}

SubType.prototype = new SuperType();

// 在此处给子类型添加方法,一定要在实现继承之后,否则会在将指针指向父类型的实例,则方法为空
SubType.prototype.getSubValue = function() {
  return this.subproperty;
}


/* 以下为测试代码示例 */
var instance1 = new SubType(['wuyuchang', 'Jack', 'Nick']);
instance1.name.push('hello');
instance1.test.push('h5');
instance1.color.push('blue');
instance1.testFun();            // http://tools.jb51.net/
alert(instance1.name);            // wuyuchang,Jack,Nick,hello
alert(instance1.getSuerperValue());      // true
alert(instance1.test);            // h1,h2,h3,h4,h5    
alert(instance1.getSubValue());        // false    
alert(instance1.color);            // pink,yellow,blue

var instance2 = new SubType('wyc');
instance2.testFun();            // http://tools.jb51.net/
alert(instance2.name);            // wyc    
alert(instance2.getSuerperValue());      // true
alert(instance2.test);            // h1,h2,h3,h4
alert(instance2.getSubValue());        // false
alert(instance2.color);            // pink,yellow
ログイン後にコピー

上記のコードは、SuperType.call(this, name); を通じて親型のプロパティを継承し、SubType.prototype = new SuperType(); を通じて親型のメソッドを継承します。上記のコードは、プロトタイプ チェーンと借用コンストラクターが遭遇する問題を都合よく解決し、JavaScript で最も一般的に使用されるインスタンス継承メソッドになっています。ただし、混合モードには欠点がないわけではありません。上記のコードでは、メソッドを継承するときに、実際には親型のプロパティが継承されていることがわかります。ただし、この時点では参照型が共有されているため、それが呼び出されます。サブタイプのコンストラクターで 2 回呼び出すと、親型のコンストラクターは親型のプロパティを継承し、プロトタイプで継承されたプロパティを上書きします。コンストラクターを 2 回呼び出す必要はありませんが、これを解決する方法はありますか?この問題を解く際に、次の2つのパターンを見てみましょう。

プロトタイプの継承

プロトタイプ継承の実装方法は、通常の継承とは異なります。プロトタイプ継承では、厳密な意味ではコンストラクターを使用せず、カスタム型を作成せずに、既存のオブジェクトに基づいて新しいオブジェクトを作成します。 。具体的なコードは次のとおりです:

function object(o) {
  function F() {}
  F.prototype = o;
  return new F();
}
ログイン後にコピー

コード例:

/* 原型式继承 */
function object(o) {
  function F() {}
  F.prototype = o;
  return new F();
}

var person = {
  name : 'wuyuchang',
  friends : ['wyc', 'Nicholas', 'Tim']
}

var anotherPerson = object(person);
anotherPerson.name = 'Greg';
anotherPerson.friends.push('Bob');

var anotherPerson2 = object(person);
anotherPerson2.name = 'Jack';
anotherPerson2.friends.push('Rose');

alert(person.friends);  // wyc,Nicholas,Tim,Bob,Rose

ログイン後にコピー

寄生継承

/* 寄生式继承 */
function createAnother(original) {
  var clone = object(original);
  clone.sayHi = function() {
    alert('hi');
  }
  return clone;
}
ログイン後にコピー

使用例:

/* 原型式继承 */
function object(o) {
  function F() {}
  F.prototype = o;
  return new F();
}
   
/* 寄生式继承 */
function createAnother(original) {
  var clone = object(original);
  clone.sayHi = function() {
    alert('hi');
  }
  return clone;
}

var person = {
  name : 'wuyuchang',
  friends : ['wyc', 'Nicholas', 'Rose']
}
var anotherPerson = createAnother(person);
anotherPerson.sayHi();
ログイン後にコピー

寄生组合式继承

  前面说过了JavaScrip中组合模式实现继承的缺点,现在我们就来解决它的缺点,实现思路是,对于构造函数继承属性,而原型链的混成形式继承方法,即不用在继承方法的时候实例化父类型的构造函数。代码如下:

function object(o) {
  function F() {}
  F.prototype = o;
  return new F();
}

/* 寄生组合式继承 */
function inheritPrototype(subType, superType) {
  var prototype = object(superType.prototype);
  prototype.constructor = subType;
  subType.prototype = prototype;
}
ログイン後にコピー

而在使用时只需要将组合模式中的“SubType.prototype = new SuperType();”这行代码替换成inheritPrototype(subType, superType);即可。寄生组合式继承的高效率体现在它只调用了一次父类型构造函数,避免了创建不必要的或多余的属性。与此同时,原型链还能保持不变,因此,还能够正常使用instanceof和isPrototypeof()。这也是目前来说最理想的继承方式了,目前也在向这种模式转型。(YUI也使用了这种模式。)

此博文参考《JavaScript高级程序设计第3版》,代码为经过改写,更具体,并加了注释使大家更易懂。如对JS继承方面有独到见解的童鞋不别吝啬,回复您的见解供大家参考!

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

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

C++関数継承の詳しい解説:継承で「基底クラスポインタ」と「派生クラスポインタ」を使うには? C++関数継承の詳しい解説:継承で「基底クラスポインタ」と「派生クラスポインタ」を使うには? May 01, 2024 pm 10:27 PM

関数の継承では、「基底クラス ポインター」と「派生クラス ポインター」を使用して継承メカニズムを理解します。基底クラス ポインターが派生クラス オブジェクトを指す場合、上方変換が実行され、基底クラスのメンバーのみにアクセスされます。派生クラス ポインターが基本クラス オブジェクトを指す場合、下向きキャストが実行される (安全ではない) ため、注意して使用する必要があります。

PHP エラーの解決: 親クラスの継承時に問題が発生しました PHP エラーの解決: 親クラスの継承時に問題が発生しました Aug 17, 2023 pm 01:33 PM

PHP エラーの解決: 親クラスの継承時に発生する問題 PHP では、継承はオブジェクト指向プログラミングの重要な機能です。継承により、元のコードを変更することなく、既存のコードを再利用し、拡張および改善できます。継承は開発で広く使用されていますが、親クラスから継承するときにエラーの問題が発生することがあります。この記事では、親クラスから継承するときに発生する一般的な問題の解決に焦点を当て、対応するコード例を示します。質問 1: 親クラスが見つかりません。親クラスの継承処理中に、システムが親クラスを見つからない場合、

C++ 関数の継承の詳細な説明: 継承のエラーをデバッグするには? C++ 関数の継承の詳細な説明: 継承のエラーをデバッグするには? May 02, 2024 am 09:54 AM

継承エラーのデバッグのヒント: 正しい継承関係を確認します。デバッガーを使用してコードをステップ実行し、変数値を調べます。仮想修飾子を正しく使用してください。隠れた相続によって引き起こされる相続ダイアモンド問題を調べてください。抽象クラスに実装されていない純粋仮想関数がないか確認します。

C++ 関数の継承の詳細な説明: 継承における 'is-a' と 'has-a' の関係を理解するには? C++ 関数の継承の詳細な説明: 継承における 'is-a' と 'has-a' の関係を理解するには? May 02, 2024 am 08:18 AM

C++の関数継承を詳しく解説:「is-a」と「has-a」の関係をマスターしよう 関数継承とは?関数の継承は、派生クラスで定義されたメソッドを基本クラスで定義されたメソッドに関連付ける C++ の手法です。これにより、派生クラスが基本クラスのメソッドにアクセスしてオーバーライドできるようになり、基本クラスの機能が拡張されます。 「is-a」および「has-a」関係 関数継承では、「is-a」関係は、派生クラスが基本クラスのサブタイプであること、つまり、派生クラスが基本クラスの特性と動作を「継承」することを意味します。基本クラス。 「has-a」関係は、派生クラスに基本クラス オブジェクトへの参照またはポインターが含まれていること、つまり、派生クラスが基本クラス オブジェクトを「所有」していることを意味します。構文関数継承を実装する方法の構文は次のとおりです: classDerivedClass:pu

継承とポリモーフィズムは C++ のクラス結合にどのような影響を与えますか? 継承とポリモーフィズムは C++ のクラス結合にどのような影響を与えますか? Jun 05, 2024 pm 02:33 PM

継承とポリモーフィズムはクラスの結合に影響します。派生クラスは基本クラスに依存するため、継承により結合が増加します。ポリモーフィズムにより、オブジェクトは仮想関数と基本クラス ポインターを通じて一貫した方法でメッセージに応答できるため、結合が軽減されます。ベスト プラクティスには、継承を控えめに使用すること、パブリック インターフェイスを定義すること、基本クラスへのデータ メンバーの追加を回避すること、依存関係の注入を通じてクラスを分離することが含まれます。ポリモーフィズムと依存性注入を使用して銀行口座アプリケーションの結合を軽減する方法を示す実践的な例。

PHP でポリモーフィズムと継承を使用してデータ型を処理する方法 PHP でポリモーフィズムと継承を使用してデータ型を処理する方法 Jul 15, 2023 pm 07:41 PM

PHP でデータ型を処理するためにポリモーフィズムと継承を使用する方法 はじめに: PHP では、ポリモーフィズムと継承は 2 つの重要なオブジェクト指向プログラミング (OOP) 概念です。ポリモーフィズムと継承を使用することで、さまざまなデータ型をより柔軟に処理できます。この記事では、ポリモーフィズムと継承を使用して PHP でデータ型を処理する方法を紹介し、コード例を通じてその実際の応用例を示します。 1. 継承の基本概念 継承はオブジェクト指向プログラミングにおける重要な概念であり、親クラスのプロパティとメソッドを継承できるクラスを作成できます。

継承した Java プログラムを使用して定期預金 (FD) および定期預金 (RD) の利息を計算します 継承した Java プログラムを使用して定期預金 (FD) および定期預金 (RD) の利息を計算します Aug 20, 2023 pm 10:49 PM

継承は、あるクラスのプロパティと動作に別のクラスからアクセスできるようにする概念です。メソッドやメンバ変数を継承するクラスをスーパークラスまたは親クラスと呼び、メソッドやメンバ変数を継承するクラスをサブクラスまたはサブクラスと呼びます。 Javaでは、クラスを継承するために「extends」キーワードを使用します。この記事では、相続を利用して定期預金や定期預金の利息を計算する Java プログラムについて説明します。まず、ローカル マシンの IDE でこれら 4 つの Java ファイル Acnt.java を作成します。このファイルには、金利や金額などの口座詳細を保存するために使用される抽象クラス「Acnt」が含まれます。また、計算用のパラメータ「amnt」を持つ抽象メソッド「calcIntrst」も含まれます。

Javaを使用してプロキシ最終クラスの継承を強制するにはどうすればよいですか? Javaを使用してプロキシ最終クラスの継承を強制するにはどうすればよいですか? Sep 06, 2023 pm 01:27 PM

Javaを使用してプロキシ最終クラスの継承を強制するにはどうすればよいですか? Java では、final キーワードはクラス、メソッド、変数を変更するために使用され、継承、オーバーライド、または変更できないことを示します。ただし、場合によっては、特定のニーズを達成するために、最終クラスの継承を強制する必要がある場合があります。この記事では、プロキシ パターンを使用してそのような機能を実装する方法について説明します。プロキシ パターンは、別のオブジェクト (プロキシ オブジェクト) の動作を制御できる中間オブジェクト (プロキシ オブジェクト) を作成できるようにする構造設計パターンです。

See all articles