フロントエンド面接必須のJavaScript対象向けプログラミング(二):コンストラクションの継承

4432 ワード

このシリーズの第1の部分では、主にどのように「パッケージ」データと方法が紹介されていますか?
今日紹介するのは、対象となる「継承」の5つの方法です.例えば、現在は「動物」のオブジェクトの構造関数があります.
function Animal(){
  this.species = "  ";
}
もう一つの「猫」の対象の構造関数があります.
function Cat(name){
 this.name = name;
}
「猫」に「動物」を受け継ぐにはどうすればいいですか?
一、コンストラクタバインディング
第一の方法も最も簡単な方法で、callまたはapply方法を使っていません.親オブジェクトの構造関数をサブオブジェクトに結合します.すなわち、サブオブジェクトの構造関数に行を加えます.
function Cat(name){
 Animal.apply(this, arguments);//this  Animal
 this.name = name;
}
var cat1 = new Cat('  ');
alert(cat1.species)
二、プロタイプ
第二の方法は、プロトタイプの属性を使う場合、「猫」のプロトタイプのオブジェクトがAnimalのインスタンスを指す場合、すべての「猫」のインスタンスは、Animalを継承することができます.
Cat.prototype = new Animal()
Cat.prototype.constructor = Cat;
var cat1 = new Cat("  ");
alert(cat1.species)//  
コードの最初の行は、CatのprototypeオブジェクトをAnimalの例に指します.
Cat.prototype = new Animal();
プロトタイプオブジェクトの元の値を完全に削除し、新しい値を付与するのに相当します.でも、二行目はどういう意味ですか?
Cat.prototype.constructor = Cat;
元々は、どのプロトタイプのオブジェクトにもconstructor属性があり、その構造関数を指しています.もし「Cat.prototype=new Animal」がないなら、Cat.prototype.com nstructorはCatを指します.この行を加えると、Cat.prototype.com nstructorはアニマルを指します.
alert(Cat.prototype.constructor == Animal); //true
さらに重要なのは、各インスタンスにもconstructor属性があり、デフォルトではprototypeオブジェクトのconstructor属性を呼び出します.
alert(cat1.constructor == Cat.prototype.constructor); // true
そこで、「Cat.prototype=new Animal」を実行した後、cat 1.
alert(cat1.constructor == Animal); // true
これは明らかに相続チェーンの乱れを引き起こすので、Cat.prototypeオブジェクトのconstructtor値をCatに変更しなければならない.これは二行目という意味です.
これは非常に重要な点であり、プログラミング時は必ず遵守してください.以下はこの点に従います.つまりプロトタイプのオブジェクトが入れ替わったら.
o.protitype = { };
次のステップは必ず新しいプロジェクトオブジェクトにconstructor属性を追加し、この属性を元のコンストラクタに向ける.
o.prototype.constructor =  o;
三、直接プロタイプを継承する
第三の方法は第二の方法の改善である.アニマルオブジェクトのため、不変の属性はそのままAnimal.prototypeに書き込むことができます.ですから、アニマルをスキップしてアニマルをそのまま引き継ぐこともできます.
まず、アニマルの対象を書き換えます.
function Animal(){ }
Animal.prototype.species = "  ";
そして、CatのprototypeをAnimalのprototypeに向けて継承を完了しました.
Cat.prototype = Animal.prototype;
Cat.prototype.constructor = Cat;
var cat1 = new Cat("  ");
alert(cat1.species); //  
前の方法と比較して、このようにする利点は効率が高い(Animalの例を実行したり構築したりしない)ことで、省メモリを比較することです.欠点はCat.prototypeとAnimal.prototypeが同じ対象を指しているので、どのようなCat.prototypeの修正もAnimal.prototypeに反映されます.
ですから、上のコードは問題があります.二行目を見てください
Cat.prototype.constructor = Cat;
この文は実際にアニマル.プロタイプのオブジェクトのconstructor属性も修正されました.
alert(Animal.prototype.constructor); // Cat
四、空いているオブジェクトを仲介として利用する
「直接プロトタイプを継承する」という欠点があるので、第四の方法があります.
var F = function (){}
F.prototype = Animal.prototype;
Cat.prototype = new F();
Cat.prototype.constructor = Cat;
Fは空対像ですので、メモリはほとんど使われません.この場合、Catのprototypeオブジェクトを修正すると、Animalのprototypeに影響を与えず、Animalのprototypeオブジェクトに影響を与えません.
alert(Animal.prototype.constructor); // Animal
上記の方法を関数としてカプセル化して使いやすいです.
function extend(Child, Parent){
   var F = function(){};
   F.prototype = Parent.prototype;
   Child.prototype = new F();
   Child.prototype.constructor = Child;
   Child.uber = Parent.prototype;
}
使う時の方法は次の通りです.
extend(Cat, Animal);
var cat1 = new Cat("  ")
alert(cat1.species); //   
このexted関数は、YUIライブラリが継承を実現する方法です.また、1点、関数の最後の行を説明します.
Child.uber = Parent.prototype;
サブオブジェクトにuber属性を設定し、この属性は直接親オブジェクトのプロトタイプ属性を指すという意味です.(uberはドイツ語で、「上へ」「上へ」という意味です.)これは子供の対象に通路を開くのと同じで、直接に親の発給を呼び出すことができます.この行はここに置いてあります.継承を実現するための完成形です.まさに予備の性質です.
五、コピー引継ぎ
上記はプロトタイプのオブジェクトを採用し、継承を実現します.私達も考え方を変えて、純粋に「コピー」の方法を採用して継承を実現できます.簡単に言えば、親オブジェクトの属性と方法を全部コピーすれば、子オブジェクトにコピーしても継承が可能ではないですか?これで私達は第5の方法があります.
まず、Animalのすべての不変の属性をそのprototypeの対象に置くことです.
function Animal(){}
Animal.prototype.species = "  "
それから、もう一つの関数を書いて、属性コピーの目的を実現します.
function extend2(Child, Parent){
  var p = Parent.prototyoe;
  var c = Child .prototype;
    for(var i in  p){
        c[i] = p[i]
    }
  c.uber = p
}
この関数の役割は、親のオブジェクトのプロトタイプのオブジェクトの属性を、Childオブジェクトのプロトタイプのオブジェクトに1つずつコピーして使う場合です.
extend2(Cat, Animal);
var cat1 = new Cat("  ");
alert(cat1.species); //   
(本シリーズは未完です.第三部分の『非構造関数の継承』を読み続けてください.)