天天看點

補基礎之javascript面向對象-構造函數的繼承

一、 構造函數綁定

  • 使用call或apply方法,将父對象的構造函數綁定在子對象上
function Animal(){
    this.species = "動物";
}
function Cat(name,color){
    Animal.apply(this, arguments);
    this.name = name;
    this.color = color;
}
var cat1 = new Cat("大毛","黃色");
console.log(cat1.species);
console.log(Cat.prototype);
console.log(Cat.constructor);
console.log(cat1.constructor);
           

二、 prototype模式

  • 将子對象(Cat)的prototype對象,指向父對象(Animal)的執行個體
  • 任何一個prototype對象都有一個constructor屬性,指向它的構造函數(此例為Cat),但是因為第一行把Cat的prototype原型對象指向了Animal,是以需要手動改回Cat,否則會導緻繼承鍊的紊亂,這是很重要的一點,程式設計時務必要遵守
  • 即替換了如果替換了prototype原型對象,下一步必然是為新的prototype對象加上constructor屬性,并将這個屬性指回原來的構造函數
function Animal(){
    this.species = "動物";
}
function Cat(name,color){
    this.name = name;
    this.color = color;
}
Cat.prototype = new Animal();   //完全删除了prototype 對象原先的值,然後賦予一個新值。
console.log(Cat.prototype.constructor) //Animal
Cat.prototype.constructor = Cat;  //防止繼承鍊紊亂
console.log(Cat.prototype.constructor); //Cat
var cat1 = new Cat("大毛","黃色");
console.log(cat1.species);  //動物
console.log(cat1.constructor);  //Cat
           

三、 直接繼承prototype

  • 第三種方法是對第二種方法的改進。由于Animal對象中,不變的屬性都可以直接寫入Animal.prototype。是以,我們也可以讓Cat()跳過 Animal(),直接繼承Animal.prototype。
  • 與前一種方法相比,這樣做的優點是效率比較高(不用執行和建立Animal的執行個體了),比較省記憶體。缺點是 Cat.prototype和Animal.prototype現在指向了同一個對象,那麼任何對Cat.prototype的修改,Animal.prototype也跟着修改。
function Animal(){ }
Animal.prototype.species = "動物";
function Cat(name,color){
    this.name = name;
    this.color = color;
}
Cat.prototype = Animal.prototype;
Cat.prototype.constructor = Cat;
var cat1 = new Cat("大毛","黃色");
console.log(cat1.species); // 動物
Cat.prototype.weight = ;  //給Cat的原型添加屬性
console.log(Cat.prototype)      //多了weight屬性
console.log(Animal.prototype)   //多了weight屬性
           

四、 利用空對象作為中介

- 跟直接繼承差不多,隻是多了個空對象作為中介,空對象幾乎不占記憶體

function Animal(){}
Animal.prototype.species = "動物";
function Cat(name,color){
    this.name = name;
    this.color = color;
}
var F = function(){};
F.prototype = Animal.prototype;
Cat.prototype = new F();
Cat.prototype.constructor = Cat;
Cat.prototype.weight = ;
var cat = new Cat('星星','黑白');
console.log(cat.species);
console.log(Animal.prototype.constructor);
console.log(Cat.prototype.constructor);

//繼承方法的封
function extend(Child, Parent) {
  var F = function(){};
  F.prototype = Parent.prototype;
  Child.prototype = new F();
  Child.prototype.constructor = Child;
  Child.uber = Parent.prototype;
  //意思是為子對象設一個uber屬性,這個屬性直接指向父對象的prototype屬性。這等于在子對象上打開一條通道,可以直接調用父對象的方法。這一行放在這裡,隻是為了實作繼承的完備性,純屬備用性質。
}
           

五、 拷貝繼承

  • 把父對象的所有屬性和方法,拷貝進子對象
  • -
function Animal(){}
Animal.prototype.species = "動物";
function Cat(name,color){
    this.name = name;
    this.color = color;
}
//封裝拷貝繼承方法
function extend(Child, Parent) {
    var p = Parent.prototype;
    var c = Child.prototype;
    for (var i in p) {
        c[i] = p[i];
    }
    c.uber = p;
}
extend(Cat, Animal);
var cat = new Cat("大毛","黃色");
console.log(cat.species);
Cat.prototype.weight = 
console.log(Cat.prototype)
console.log(Animal.prototype)
           

繼續閱讀