ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScriptの6つの継承方法(画像とテキスト)を深く理解する

JavaScriptの6つの継承方法(画像とテキスト)を深く理解する

黄舟
黄舟オリジナル
2017-03-24 14:44:191056ブラウズ

この記事は、JavaScript の 6 つの 継承 メソッドを再理解するのに役立ちます。これは非常に優れており、必要な友人は参照することができます

クラスベースの継承 (コンストラクター)。

実はJSにはクラスという概念はなく、いわゆるクラスもシミュレートされます。特に新しいキーワードを使用すると、「クラス」の概念は他の言語のクラスに似てきます。クラスの継承とは、関数オブジェクト内で親クラスのコンストラクターを呼び出し、親クラスのメソッドやプロパティを取得できるようにすることです。 call メソッドと apply メソッドは、クラスの継承をサポートします。これの動作環境を変更することで、サブクラス自体が親クラスの様々な属性を持ちます。

var father = function() {
this.age = 52;
this.say = function() {
alert('hello i am '+ this.name ' and i am '+this.age + 'years old');
}
}
var child = function() {
this.name = 'bill';
father.call(this);
}
var man = new child();
man.say();

プロトタイプの継承

プロトタイプの継承は開発でよく使用されます。継承はオブジェクト自体ではなく、オブジェクトのプロトタイプ (プロトタイプ) で行われるため、クラスの継承とは異なります。すべてのオブジェクトにはプロトタイプがあり、ブラウザに非表示の proto 属性として反映されます。一部の最新のブラウザでは、それらを変更できます。たとえば、zepto では、空の 配列 の proto 属性に zepto の fn オブジェクトを追加すると、配列は zepto オブジェクトになり、すべてのメソッドが含まれます。ただし、オブジェクトがメソッドを呼び出す必要がある場合、メソッドが見つからない場合は、最も近いプロトタイプに戻り、再度下方向に検索を続けます。このようにして、探している方法が見つかるまで、段階的に検索しました。 これらのルックアップされたプロトタイプは、オブジェクトのプロトタイプ チェーンを形成します。プロトタイプは最終的に null を指します。プロトタイプ継承と呼ばれるものは、親オブジェクトのメソッドを子クラスのプロトタイプに転送することです。これらのメソッドとプロパティは、サブクラスのコンストラクターでは使用できません。

var father = function() {
}
father.prototype.a = function() {
}
var child = function(){}
//开始继承
child.prototype = new father();
var man = new child();
man.a();

7行目でプロトタイプの継承が実装されていることがわかります。この方法は多くの人によく知られています。ブラウザで man を表示すると、各プロトタイプの継承関係を確認できます。

子 ->オブジェクト (父によってインスタンス化されたオブジェクト) ->父という階層関係がわかります。子は父親のプロトタイプにあるものを中間層を介して継承します。しかし、なぜ中央にオブジェクトの層があるのでしょうか? child.prototype = Father.prototype と設定しないのはなぜでしょうか。 そうすれば、子供も父親も変わりません、というのが答えです。プロトタイプにはコンストラクターを指すコンストラクター属性があることを覚えておく必要があります。通常の状況では、コンストラクターの値を変更して、子のコンストラクターを指すように戻す必要があります。しかし、father.prototype が child.prototype に直接割り当てられている場合、コンストラクターは誰を指すのでしょうか?したがって、子供と父親は中間層を通じてのみ独立したオブジェクトとして維持できることは明らかです。

クラスベースの継承とプロトタイプ継承の比較

コンストラクター(クラス)の継承

まず、コンストラクターから継承されたメソッドは親オブジェクトに格納され、インスタンスごとに、関数はメモリ内に保存されるため、このアプローチではパフォーマンス上の問題はまったく発生しません。

第二に、クラスの継承は不変です。実行時に再利用することはできません。このメソッドは自己完結型のデッドメソッドです。実際には、単純に使用されることはほとんどありません。

プロトタイプの継承

利点:

プロトタイプチェーンは変更可能: プロトタイプチェーン上の親クラスは置換可能で拡張可能です

プロトタイプリンクを変更することでサブクラスを変更できます。また、クラスの継承は多重継承をサポートしていませんが、プロトタイプの継承の場合は、 extend を書くだけでオブジェクトを拡張できます。

しかし、プロトタイプチェーンの継承にも 2 つの問題があります。

まず、reference型の値を含むプロトタイプ属性はすべてのインスタンスで共有されます(次のように理解できます: sub1.arr.push(2) を実行します。最初にsub1で属性検索を実行し、すべてのインスタンス属性を検索します) (この場合 (インスタンス属性はありません)、それが見つからなかったので、プロトタイプ チェーンを検索し始め、sub1 のプロトタイプ オブジェクトを取得しました。検索した後、arr 属性があることがわかりました。 , そのため、arr の最後に 2 を挿入したので、sub2.arr も変更されました)。

2 番目に、サブタイプのインスタンスを作成する場合、パラメーターをスーパータイプのコンストラクターに渡すことはできません。 (実際、すべてのオブジェクト インスタンスに影響を与えずにスーパータイプのコンストラクターにパラメーターを渡す方法はないと言うべきです。) 実際には、純粋なプロトタイプ チェーンが使用されることはほとんどありません。

function Super(){
this.val = 1;
this.arr = [1];
}
function Sub(){
// ...
}
Sub.prototype = new Super(); // 核心
var sub1 = new Sub();
var sub2 = new Sub();
sub1.val = 2;
sub1.arr.push(2);
alert(sub1.val); // 2
alert(sub2.val); // 1
alert(sub1.arr); // 1, 2
alert(sub2.arr); // 1, 2

概要:

クラス継承をインスタンス化するとき、親クラスはパラメータを渡すことができますが、再利用することはできません (親クラスは不変であり、各インスタンスは親クラスの内容をメモリに保存します)

原型继承在实例化时,父类不可传参,可以复用(原型链可改变(父类可替换可扩展),父类不会保存在内存中,而是顺着原型链查找,但是结果是原型属性会被所有实例共享(尤其影响引用类型值))

组合继承(最常用)

组合继承将原型链和借用构造函数的技术结合到一起,发挥两者之长的一种继承模式。

思路是使用原型链实现对原型属性和方法的继承,通过借用构造函数实现对实例属性的继承。

function SuperType(name){
this.name = name;
this.numbers = [1,2,3];
}
SuperType.prototype.sayName = function(){
console.log(this.name);
}
function SubType(name,age){
SuperType.call(this,name);
this.age = age;
}
SubType.prototype = new SuperType();
SubType.prototype.sayAge = function(){
console.log(this.age);
}
var instance1 = new SubType('aaa',21);
instance1.numbers.push(666);
console.log(instance1.numbers);
instance1.sayName();
instance1.sayAge();
var instance2 = new SubType('bbb',22);
console.log(instance2.numbers);
instance2.sayName();
instance2.sayAge();

把实例函数都放在原型对象上,通过Sub.prototype = new Super();继承父类函数,以实现函数复用。

保留借用构造函数方式的优点,通过Super.call(this);继承父类的基本属性和引用属性,以实现传参;

优缺点

优点:

  1. 可传参

  2. 函数可复用

  3. 不存在引用属性共享问题(图纸)

缺点:

(一点小瑕疵)子类原型上有一份多余的父类实例属性,因为父类构造函数被调用了两次,生成了两份,而子类实例上的那一份屏蔽了子类原型上的。。。又是内存浪费,比刚才情况好点,不过确实是瑕疵。

以上がJavaScriptの6つの継承方法(画像とテキスト)を深く理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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