JavaScript で継承を実装する 6 つの方法

黄舟
リリース: 2017-10-23 09:44:21
オリジナル
1413 人が閲覧しました

JavaScript における継承の説明:

多くのオブジェクト指向言語は、インターフェース継承と実装継承という 2 つの継承方法をサポートしています。インターフェイスの継承はメソッドの署名のみを継承しますが、実装の継承は実際のメソッドを継承します。 JavaScript では、関数にシグネチャがないためインターフェイスの継承は実装できませんが、実装の継承のみがサポートされており、実装の継承は主にプロトタイプ チェーンを通じて実現されます。 ️まず、プロトタイプチェーンの説明を引用します。基本的な考え方は、プロトタイプを使用して、ある参照型に別の参照型のプロパティとメソッドを継承させることです。参照タイプ。この概念を理解するには、まずコンストラクター、プロトタイプ、インスタンスの関係を明確にする必要があります。各コンストラクター (関数である限り) には、オブジェクトを指すプロトタイプ属性があります (このオブジェクトはコンストラクターのプロトタイプ オブジェクトです)。 ); プロトタイプ オブジェクト (オブジェクトである限り) にはコンストラクターを指すコンストラクター属性があり、インスタンスにはプロトタイプ オブジェクトを指す内部ポインター [[Prototype]] が含まれます。率直に言うと、プロトタイプ チェーンの構築は、ある型のインスタンスを別のコンストラクターのプロトタイプに割り当てることによって実現されます。これにより、サブタイプはスーパータイプで定義されたすべてのプロパティとメソッドにアクセスできるようになります。各オブジェクトには独自のプロトタイプ オブジェクトがあり、プロトタイプ オブジェクトをテンプレートとして使用して、プロトタイプ オブジェクトからプロパティとメソッドを継承します。また、プロトタイプ オブジェクトは独自のプロトタイプを持ち、そこからレイヤーごとにプロパティやメソッドを継承することもできます。この関係はプロトタイプ チェーンと呼ばれ、あるオブジェクトが他のオブジェクトでプロパティとメソッドを定義している理由を説明します。



JavaScript で継承を実装する 6 つの方法:

1. プロトタイプチェーン

2. コンストラクターの借用


3. 結合継承 (プロトタイプチェーンを組み合わせて使用​​し、コンストラクターを借用)


4. プロトタイプ継承


5. 寄生継承


6. 寄生結合継承 (結合結合継承と寄生継承を使用)

1.トタイプチェーン

// 实现原型链的一种基本模式
function SuperType(){
            this.property = true;
}
SuperType.prototype.getSuperValue = function(){
            return this.property;
};
function SubType(){
            this.subproperty = false;
}

// 继承,用 SuperType 类型的一个实例来重写 SubType 类型的原型对象
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function(){
            return this.subproperty;
};
var instance = new SubType();
alert(instance.getSuperValue());     // true
ログイン後にコピー

追記: SubType は SuperType を継承し、継承は SuperType のインスタンスを作成し、そのインスタンスを SubType のプロトタイプに割り当てることで実現されます。実装の本質は、サブタイプのプロトタイプ オブジェクトをオーバーライドし、新しいタイプのインスタンスに置き換えることです。サブタイプの新しいプロトタイプ オブジェクトには、SuperType プロトタイプを指す内部プロパティ [[Prototype]] と、SuperType コンストラクターを指す SuperType プロトタイプから継承されたプロパティ コンストラクターがあります。最終的なプロトタイプ チェーンは次のようになります。インスタンスは SubType のプロトタイプを指し、SubType のプロトタイプは SuperType のプロトタイプを指し、SuperType のプロトタイプは Object のプロトタイプを指します (すべての関数のデフォルトのプロトタイプは Object のインスタンスです)したがって、デフォルトのプロトタイプには Object.prototype への内部ポインターが含まれます)。
プロトタイプ チェーンの欠点:
1. プロトタイプを介して継承が実装される場合、プロトタイプは実際には別の型のインスタンスになります。その結果、元のインスタンスの属性が自然に現在のプロトタイプ属性になり、すべてのインスタンスで共有されます。このように理解してください。スーパータイプ コンストラクターで定義された参照型値のインスタンス プロパティは、サブタイプ プロトタイプのプロトタイプ プロパティになり、すべてのサブタイプ インスタンスによって共有されます。
2. サブタイプのインスタンスを作成する場合、スーパータイプのコンストラクターにパラメーターを渡すことはできません。

2. コンストラクターの借用 (偽のオブジェクトまたはクラシック継承とも呼ばれます)

// 在子类型构造函数的内部调用超类型构造函数;使用 apply() 或 call() 方法将父对象的构造函数绑定在子对象上
function SuperType(){
            // 定义引用类型值属性
            this.colors = ["red","green","blue"];
}
function SubType(){
            // 继承 SuperType,在这里还可以给超类型构造函数传参
            SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push("purple");
alert(instance1.colors);     // "red,green,blue,purple"

var instance2 = new SubType();
alert(instance2.colors);     // "red,green,blue"
ログイン後にコピー

PS: apply() または call() メソッドを使用することで、作成される SubType インスタンスのコンテキストで実際に SuperType コンストラクターを呼び出します。 。これにより、SuperType() 関数で定義されたすべてのオブジェクト初期化コードが新しい SubType オブジェクトに対して実行されます。その結果、SubType の各インスタンスは、colors プロパティの独自のコピーを持つことになります。
コンストラクターを借用することの利点は、プロトタイプ チェーン実装の継承に関する 2 つの問題が解決されることです。コンストラクターを借用することの欠点は、メソッドがすべてコンストラクター内で定義されているため、関数の再利用ができないことです。さらに、スーパータイプのプロトタイプで定義されたメソッドはサブタイプには表示されないため、すべてのタイプはコンストラクター パターンのみを使用できます。

3. 組み合わせ継承 (擬似古典継承とも呼ばれます)

// 将原型链和借用构造函数的技术组合到一块。使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。
这样,既通过在原型上定义方法实现了函数复用,又能够保证每个实例都有自己的属性。
function SuperType(name){
            this.name = name;
            this.colors = ["red","green","blue"];
}
SuperType.prototype.sayName = function(){
            alert(this.name);
};
function SubType(name,age){
            // 借用构造函数方式继承属性
            SuperType.call(this,name);
            this.age = age;
}
// 原型链方式继承方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
            alert(this.age);
};
var instance1 = new SubType("luochen",22);
instance1.colors.push("purple");
alert(instance1.colors);      // "red,green,blue,purple"
instance1.sayName();
instance1.sayAge();

var instance2 = new SubType("tom",34);
alert(instance2.colors);      // "red,green,blue"
instance2.sayName();
instance2.sayAge();
ログイン後にコピー

PS: 組み合わせ継承は、プロトタイプ チェーンと借用コンストラクターの欠点を回避し、それらの利点を組み合わせたもので、JavaScript で最も一般的に使用される継承パターンになります。さらに、instanceof 演算子と isPrototype() メソッドを使用して、構成継承に基づいて作成されたオブジェクトを識別することもできます。ただし、独自の欠点もあります。最大の問題は、状況に関係なく、スーパータイプ コンストラクターが 2 回呼び出されることです。1 回はサブタイプ プロトタイプの作成時、もう 1 回はサブタイプ コンストラクター内で呼び出されます。

4. プロトタイプの継承

// 借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。
1、自定义一个函数来实现原型式继承
function object(o){
            function F(){}
            F.prototype = o;
            return new F();
}
ログイン後にコピー

PS: object() 関数内で、最初に一時的なコンストラクターを作成し、次にこのコンストラクターのプロトタイプとして受信オブジェクトを使用し、最後にこの一時的な型の新しいバージョンを返します。基本的に、object() は、渡されたオブジェクトの浅いコピーを実行します。
2. Object.create() メソッドを使用してプロトタイプの継承を実装します。このメソッドは 2 つのパラメータを受け入れます。新しいオブジェクトのプロトタイプとして使用されるオブジェクトと、新しいオブジェクトの追加プロパティを定義するオブジェクトです。このメソッドは、1 つのパラメーターが渡された場合、object() メソッドと同じように機能します。
2 番目のパラメーターを渡すと、指定されたプロパティはプロトタイプ オブジェクトの同じ名前のプロパティをオーバーライドします。

var person = {
            name: "luochen",
            colors: ["red","green","blue"]
}; 
var anotherPerson1 = Object.create(person,{
            name: {
                    value: "tom"
            }
});
var anotherPerson2 = Object.create(person,{
            name: {
                    value: "jerry"
            }
});
anotherPerson1.colors.push("purple");
alert(anotherPerson1.name);     // "tom"
alert(anotherPerson2.name);     // "jerry"
alert(anotherPerson1.colors);    // "red,green,blue,purple"
alert(anotherPerson2.colors);    // "red,green,bule,purple";
ログイン後にコピー

追記: あるオブジェクトを別のオブジェクトに似せたいだけの場合は、プロトタイプ継承が完全に可能です。ただし、欠点は、参照型の値を含むプロパティは常に対応する値を共有することです。

5. 寄生継承

// 创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后返回这个对象
function createPerson(original){
            var clone = Object.create(original);   // 通过 Object.create() 函数创建一个新对象
            clone.sayGood = function(){              // 增强这个对象
                        alert("hello world!!!");
            };
            return clone;                                      // 返回这个对象 
}
ログイン後にコピー

PS: 寄生継承は、カスタム型やコンストラクターの代わりにオブジェクトを主に考慮する場合にも便利なパターンです。このモードの欠点は、関数を再利用できないことです。

6. 寄生組み合わせ継承

// 通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型
function SuperType(name){
            this.name = name;
            this.colors = ["red","green","blue"];
}
SuperType.prototype.sayName = function(){
            alert(this.name);
};
function SubType(name,age){
            SuperType.call(this,name);
            this.age = age;
}
// 创建超类型原型的一个副本
var anotherPrototype = Object.create(SuperType.prototype);
// 重设因重写原型而失去的默认的 constructor 属性
anotherPrototype.constructor = SubType;
// 将新创建的对象赋值给子类型的原型
SubType.prototype = anotherPrototype;

SubType.prototype.sayAge = function(){
            alert(this.age);
};
var instance1 = new SubType("luochen",22);
instance1.colors.push("purple");
alert(instance1.colors);      // "red,green,blue,purple"
instance1.sayName();
instance1.sayAge();

var instance2 = new SubType("tom",34);
alert(instance2.colors);      // "red,green,blue"
instance2.sayName();
instance2.sayAge();
ログイン後にコピー

追伸: この例の効率の高さは、SuperType コンストラクターを 1 回だけ呼び出すため、SubType.prototype に不要で冗長なプロパティを作成することを回避できることです。同時に、プロトタイプ チェーンは変更されないため、インスタンス オペレーターと isPrototype() メソッドは通常どおり使用できます。

以上がJavaScript で継承を実装する 6 つの方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート