この記事の例では、JavaScript で継承を実装する 6 つの方法を紹介し、具体的な内容は次のとおりです。
1. [プロトタイプチェーンの継承] 実装の本質は、プロトタイプ オブジェクトを書き換えて新しい型のインスタンスに置き換えることです。実際、書き換えられたのは SubType プロトタイプのコンストラクター プロパティではなく、SubType プロトタイプは別のオブジェクト (SuperType プロトタイプ) を指し、このプロトタイプ オブジェクトのコンストラクター プロパティは SuperType
を指します。
function SuperType(){ this.property = true; } SuperType.prototype.getSuperValue = function(){ return this.property; }; function SubType(){ this.subproperty = false; } //继承了SuperType SubType.prototype = new SuperType(); SubType.prototype.getSubValue = function(){ return this.subproperty; } var instance = new SubType(); alert(instance.getSuperValue());//true
[注 1] メソッドは慎重に定義してください。プロトタイプにメソッドを追加するコードは、プロトタイプを置き換えるステートメントの後に配置する必要があります。
function SuperType(){ this.property = true; } SuperType.prototype.getSuperValue = function(){ return this.property; }; function SubType(){ this.subproperty = false; } //继承了SuperType SubType.prototype = new SuperType(); //添加了新方法 SubType.prototype.getSubValue = function(){ return this.subproperty; } //重写超类型的方法 SubType.prototype.getSuperValue = function(){ return false; } var instance = new SubType(); alert(instance.getSuperValue());//false
[注 2] プロトタイプ チェーンを介して継承を実装する場合、オブジェクト リテラルを使用してプロトタイプ メソッドを作成することはできません。これを行うと、プロトタイプ チェーンが書き換えられます。
function SuperType(){ this.property = true; } SuperType.prototype.getSuperValue = function(){ return this.property; }; function SubType(){ this.subproperty = false; } //继承了SuperType SubType.prototype = new SuperType(); //使用字面量方法添加新方法会导致上一行代码无效 SubType.prototype = { getSubValue : function(){ return this,subproperty; }, someOtherMethod : function(){ return false; } }; var instance = new SubType(); alert(instance.getSuperValue());//error
【デメリット1】サブタイプのインスタンス作成時、スーパータイプのコンストラクターにパラメータを渡すことができない
【デメリット2】参照型の値を含むプロトタイププロパティが全インスタンスで共有されてしまう
function SuperType(){ this.colors = ['red','blue','green']; } function SubType(){} //继承了SuperType SubType.prototype = new SuperType(); var instance1 = new SubType(); instance1.colors.push('black'); alert(instance1.colors);//'red,blue,green,black' var instance2 = new SubType(); alert(instance2.colors);//'red,blue,green,black'
2. [借用コンストラクターの継承 (偽のオブジェクトまたはクラシック継承とも呼ばれる)] は、 サブタイプ コンストラクター内のスーパータイプ コンストラクターを呼び出すため、apply() メソッドと call() メソッドを使用して、コンストラクターを次のようにすることもできます。今後新しく作成されるオブジェクトに対して実行されます
function SuperType(){ this.colors = ['red','blue','green']; } function SubType(){ //继承了SuperType SuperType.call(this); } var instance1 = new SubType(); instance1.colors.push('black'); alert(instance1.colors);//'red,blue,green,black' var instance2 = new SubType(); alert(instance2.colors);//'red,blue,green'
[利点] パラメータを渡す
function SuperType(name){ this.name = name; } function SubType(){ //继承了SUperType,同时还传递了参数 SuperType.call(this,"Nicholas"); //实例属性 this.age = 29; } var instance = new SubType(); alert(instance.name);//"Nicholas" alert(instance.age);//29
[注] SuperType コンストラクターがサブタイプのプロパティをオーバーライドしないようにするために、スーパータイプ コンストラクター
を呼び出した後に、サブタイプで定義する必要があるプロパティを追加できます。
function SuperType(name){ this.name = name; this.age = 30; } function SubType(){ //实例属性 this.age = 29; //继承了SUperType,同时还传递了参数 SuperType.call(this,"Nicholas"); } var instance = new SubType(); //实例属性被重写为SuperType构造函数的属性 alert(instance.age);//30
【デメリット1】関数の再利用ができない
[欠点 2] スーパータイプのプロトタイプで定義されたメソッドもサブタイプからは見えないため、すべてのタイプはコンストラクター パターン
のみを使用できます。
3. [結合継承 (擬似古典継承とも呼ばれます)] プロトタイプチェーンと借用コンストラクターの技術を組み合わせて、両方の長所を活かした継承モデル。その背後にある考え方は、プロトタイプ チェーンを使用してプロトタイプのプロパティとメソッドの継承を実現し、コンストラクターを借用してインスタンス プロパティの継承を実現することです。このように、プロトタイプでメソッドを定義することで関数の再利用が実現され、各インスタンスが独自の属性を持つことが保証されるため、JavaScript で最も一般的に使用される継承パターンとなっています。
function SuperType(name){ this.name = name; this.colors = ['red','blue','green']; } 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("Nicholas",29); instance1.colors.push("black"); alert(instance1.colors);//'red,blue,green,black' instance1.sayName();//"Nicholas" instance1.sayAge();//29 var instance2 = new SubType("Greg",27); alert(instance2.colors);//'red,blue,green' instance2.sayName();//"Greg" instance2.sayAge();//27
[欠点] いずれの場合も、スーパータイプ コンストラクターは 2 回呼び出されます。1 回はサブタイプ プロトタイプの作成時、もう 1 回はサブタイプ コンストラクター内で呼び出されます。サブタイプには最終的にスーパータイプ オブジェクトのすべてのインスタンス プロパティが含まれますが、サブタイプ コンストラクターが呼び出されるときにこれらのプロパティをオーバーライドする必要があります。
function SuperType(name){ this.name = name; this.colors = ["red","blue","green"]; } SuperType.prototype.sayName = function(){ alert(this.name); }; function SubType(name,age){ SuperType.call(this,name); // 第二次调用SuperType() this.age = age; } SubType.prototype = new SuperType(); //第一次调用SuperType() SubType.prototype.constructor = SubType; SubType.prototype.sayAge = function(){ alert(this.age); };
4. [プロトタイプの継承] プロトタイプを使用すると、カスタム型を作成せずに、既存のオブジェクトに基づいて新しいオブジェクトを作成できます。基本的に、object() は、渡されたオブジェクトの浅いコピーを実行します。
[注意] プロトタイプの継承では、別のオブジェクトの基礎として使用できるオブジェクトが必要です。そのようなオブジェクトがある場合は、それを object() 関数に渡し、取得したオブジェクトを特定のオブジェクトに従って変更できます。ニーズ
function object(o){ function F(){}; F.prototype = o; return new F(); } var person = { name: "Nicholas", friends: ["Shelby","Court","Van"] }; var anotherPerson = object(person); anotherPerson.name = "Greg"; anotherPerson.friends.push("Rob"); var yetAnotherPerson = object(person); yetAnotherPerson.name = "Linda"; yetAnotherPerson.friends.push("Barbie"); alert(person.friends);//"Shelby,Court,Van,Rob,Barbie"
【4.1】【Object.create() メソッド】: ECMAScript5 の新しい Object.create() メソッドは、プロトタイプの継承を標準化します。このメソッドは 2 つのパラメータを受け入れます。新しいオブジェクトのプロトタイプとして使用されるオブジェクトと、(オプションで) 新しいオブジェクトの追加プロパティを定義するオブジェクトです。パラメーターが渡されると、Object.create() メソッドと object() メソッドは同じように動作します
function object(o){ function F(){}; F.prototype = o; return new F(); } var person = { name: "Nicholas", friends:["Shelby","Court","Van"] }; var anotherPerson = Object.create(person); anotherPerson.name = "Greg"; anotherPerson.friends.push("Rob"); var yetAnotherPerson = object(person); yetAnotherPerson.name = "Linda"; yetAnotherPerson.friends.push("Barbie"); alert(person.friends);//"Shelby,Court,Van,Rob,Barbie"
[注意] Object.create() メソッドの 2 番目のパラメーターは、Object.defineProperties() メソッドの 2 番目のパラメーターと同じ形式です。各プロパティは独自の記述子を通じて定義されます。この方法で指定されたプロパティは、プロトタイプ オブジェクトの同じ名前のプロパティをオーバーライドします。
var person = { name: "Nicholas", friends:["Shelby","Court","Van"] }; var anotherPerson = Object.create(person,{ name: { value: "Greg" } }); alert(anotherPerson.name);//"Greg"
【4.2】下位バージョンブラウザの Object.create() メソッドと互換性があります
if(typeof Object.create != "function"){ (function(){ var F = function(){}; Object.create = function(o){ if(arguments.length > 1){ throw Error('Second argument noe supported'); } if(o === null){ throw Error("Cannot set a null [[Prototype]]"); } if(typeof o != 'Object'){ throw TypeError("Arguments must be an object"); } F.prototype = o; return new F(); } })(); }
5. [寄生継承] 継承プロセスをカプセル化するためにのみ使用される関数を作成します。この関数は、内部的に何らかの方法でオブジェクトを強化し、最終的にすべての作業を実行したように見えます。同じオブジェクト
【デメリット】関数の再利用ができない
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: "Nicholas", friends: ["Shelby","Court","Van"] }; var anotherPerson = createAnother(person); anotherPerson.sayHi();//"hi"
6. [寄生組み合わせの継承] コンストラクターを借用することでプロパティを継承し、プロトタイプ チェーンのハイブリッド形式を通じてメソッドを継承します。この背後にある基本的な考え方は、サブタイプのプロトタイプを指定するためにスーパータイプのコンストラクターを呼び出す必要はなく、必要なのはスーパータイプのプロトタイプのコピーだけであるということです。基本的に、寄生継承を使用してスーパータイプのプロトタイプから継承し、その結果をサブタイプのプロトタイプに割り当てます。寄生結合継承は、参照型にとって最も理想的な継承パラダイムです。
//这个例子中的高效率体现在它只调用了一次Super构造函数,并且因此避免了在SubType.prototype上面创建不必要的、多余的属性。与此同时,原型链还能保持不变。 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;//指定对象 } function SuperType(name){ this.name = name; this.colors = ["red","blue","green"]; } SuperType.prototype.sayName = function(){ alert(this.name); }; function SubType(name,age){ SuperType.call(this,name); this.age = age; } inheritPrototype(SubType,SuperType); SubType.prototype.sayAge = function(){ alert(this.age); }
以上がこの記事の全内容です。JavaScript で継承を実装する方法です。読んでいただいた皆様、ありがとうございます。編集部も引き続き頑張ります!