ホームページ > 記事 > ウェブフロントエンド > JavaScript オブジェクト指向プログラミング (継承実装)
多くの OO 言語は、インターフェース継承と実装継承という 2 つの継承方法をサポートしています。インターフェイスの継承はメソッドの署名のみを継承しますが、実装の継承は実際のメソッドを継承します。前に述べたように、関数には署名がないため、ECMAScript ではインターフェイスの継承はできません。 ECMAScript は実装の継承のみをサポートしており、その実装の継承は主にプロトタイプ チェーンに依存します。ここでは、プロトタイプチェーン継承、借用コンストラクター、複合継承、プロトタイプ継承、寄生継承、寄生組み合わせ継承などを中心に説明します。
1. プロトタイプ チェーン
ECMAScript は、プロトタイプ チェーンの概念を記述し、継承を実装するための主なメソッドとしてプロトタイプ チェーンを使用します。基本的な考え方は、プロトタイプを使用して、ある参照型が別の参照型のプロパティとメソッドを継承できるようにすることです。コンストラクター、プロトタイプ、インスタンスの関係を簡単に見てみましょう。各コンストラクターにはプロトタイプ オブジェクトがあり、プロトタイプ オブジェクトにはコンストラクターへのポインターが含まれ、インスタンスにはプロトタイプ オブジェクトへの内部ポインターが含まれます。では、プロトタイプ オブジェクトを別の型のインスタンスと等しくするとどうなるでしょうか?当然のことながら、この時点のプロトタイプ オブジェクトには別のプロトタイプへのポインタが含まれており、したがって、他のプロトタイプにも別のコンストラクタへのポインタが含まれています。別のプロトタイプが別のタイプのインスタンスである場合、上記の関係は依然として保持され、以下同様に層ごとに、インスタンスとプロトタイプのチェーンが形成されます。これがいわゆるプロトタイプチェーンの基本概念です。
function Person(){ this.name=”defaultName”; } Person.property.doAction=function(){ alert(“talk”); } function Student(){ this.age=5; } Student.property=new Person(); Student.property.doSome=function(){ alert(“ homework”); }
プロトタイプ チェーンは非常に強力で、継承の実装に使用できますが、いくつかの問題もあります。主な問題は、参照型の値を含むプロトタイプから発生します。参照型の値を含むプロトタイプ プロパティはすべてのインスタンスで共有されることを以前に紹介したことをまだ覚えているかもしれません。これが、プロパティをプロトタイプ オブジェクトではなくコンストラクターで定義する必要がある理由です。プロトタイプを介して継承が実装されると、プロトタイプは実際には別の型のインスタンスになります。したがって、元のインスタンスの属性が自然に現在のプロトタイプの属性になります。プロトタイプ チェーンの 2 番目の問題は、サブタイプのインスタンスを作成するときに、スーパータイプのコンストラクターにパラメーターを渡すことができないことです。実際、すべてのオブジェクト インスタンスに影響を与えずにスーパータイプのコンストラクターにパラメーターを渡す方法はないと言うべきです。このことと、参照型の値を含むプロトタイプに関する先ほど説明した問題のため、プロトタイプ チェーンだけが実際に使用されることはほとんどありません。
2. コンストラクターの借用
プロトタイプに参照型の値が含まれることによって引き起こされる問題を解決する過程で、開発者はコンストラクターの借用 (コンストラクターの盗用) と呼ばれる手法を使用し始めました (偽オブジェクトまたはクラシック継承とも呼ばれます)。 。この手法の基本的な考え方は非常に単純で、サブタイプ コンストラクター内でスーパータイプ コンストラクターを呼び出すことです。関数は特定の環境でコードを実行するオブジェクトにすぎないことを忘れないでください。そのため、apply() メソッドと call() メソッドを使用すると、(将来的に) 新しく作成されるオブジェクトに対してコンストラクターを実行することもできます。
function Person(name){ this.name=name; } Person.property.doAction=function(){ alert(“talk”); } Person.property.showName=function(){ alert(this.name); } function Student(){ Person.call(this,name); this.age=5; }
コンストラクターを借用するだけでは、コンストラクターパターンの問題を回避することはできません - メソッドはすべてコンストラクター内で定義されているため、関数の再利用は問題外です。 さらに、スーパータイプのプロトタイプで定義されたメソッドもサブタイプには見えません。その結果、すべての型はコンストラクター パターンのみを使用できます。これらの問題を考慮すると、コンストラクターを借用する手法が単独で使用されることはほとんどありません。
3. 組み合わせ継承
組み合わせ継承は、疑似古典継承とも呼ばれ、プロトタイプ チェーンと借用したコンストラクター テクノロジを組み合わせて、両方の長所を活用する継承モデルを指します。その背後にある考え方は、プロトタイプ チェーンを使用してプロトタイプのプロパティとメソッドの継承を実現し、コンストラクターを借用することでインスタンス プロパティの継承を実現することです。このように、関数の再利用はプロトタイプでメソッドを定義することによって実現され、各インスタンスは独自の属性を持つことが保証されます。
function Person(name){ this.name=name; this.loves=[“sing”,”paly games”] } Person.property.showLoves=function (){ alert(this.lovers); } function Student(name,age){ Person.class(this,name); This.age=age; } Student.property=new Person(); Student.property.constructor=Student; Student.property.showName=function(){ alert(this.name); }
結合継承は、プロトタイプ チェーンと借用コンストラクターの欠点を回避し、それらの利点を組み合わせて、JavaScript で最も一般的に使用される継承パターンになります。さらに、instanceof と isPrototypeOf() を使用して、結合された継承に基づいて作成されたオブジェクトを識別することもできます。
4. プロトタイプの継承
function object(o){ function F(){} F.prototype = o; return new F(); }
コンストラクターを作成する必要がなく、あるオブジェクトを別のオブジェクトと同様に保ちたいだけの場合は、プロトタイプの継承が完全に可能です。ただし、参照型の値を含むプロパティは、プロトタイプ パターンを使用する場合と同様に、対応する値を常に共有することを忘れないでください。
5. 寄生結合継承
いわゆる寄生結合継承とは、コンストラクターを借用してプロパティを継承し、プロトタイプ チェーンのハイブリッド形式を通じてメソッドを継承することを意味します。その背後にある基本的な考え方は、サブタイプのプロトタイプを指定するためにスーパータイプのコンストラクターを呼び出す必要はなく、必要なのはスーパータイプのプロトタイプのコピーだけであるということです。基本的に、寄生継承を使用してスーパータイプのプロトタイプを継承し、その結果をサブタイプ
のプロトタイプに代入します。寄生組み合わせ継承の基本パターンは次のとおりです。
function inheritPrototype(subType, superType){ var prototype = object(superType.prototype); //创建对象 prototype.constructor = subType; //增强对象 subType.prototype = prototype; //指定对象 }
个参数:子类型构造函数和超类型构造函数。在函数内部,第一步是创建超类型原型的一个副本。第二步是为创建的副本添加constructor 属性,从而弥补因重写原型而失去的默认的constructor 属性。最后一步,将新创建的对象(即副本)赋值给子类型的原型。这样,我们就可以用调用inheritPrototype()函数的语句,去替换前面例子中为子类型原型赋值的语句了。
集寄生式继承和组合继承的优点与一身,是实现基于类型继承的最有效方式。
以上就是JavaScript面向对象编程(继承实现方式)的内容,更多相关内容请关注PHP中文网(www.php.cn)!