JavaScript的繼承

方法1:通過原型鏈

這種模式的問題是Dog的所有實例共享同一個Animal實例,一旦在dog1種修改Animal屬性,dog2種的Animal屬性也被修改,這是我們不想看到的,因爾這種繼承并不實用。

function Animal(){
    this.Age = null;
    this.Name = null;
}

Animal.prototype.Eat = function(){
    console.log(this.Name + ' eat')
}

function Dog(){
    this.Species = null;
}

Dog.prototype = new Animal();

var dog = new Dog();
dog.Eat()
console.log(dog);

方法2:通過call 改變this

但是這種方法仍然不完美, 每個Dog的實例中都有Eat方法,我們希望方法對于每個實例都是共享的,而不是每個實例都有一樣的方法。

function Animal(age, name){
    this.Age = age;
    this.Name = name;
    this.Eat = function(){
        console.log(this.Name + ' eat');
    }
}

function Dog(species, age, name){
    this.Species = species;
    Animal.call(this, age, name);
}

var dog = new Dog('博美', '5', 'Jim');
console.log(dog);

方法3:組合繼承模式

這種方法結合了方法1和方法2。用原型鏈實現方法的繼承,在構造函數中實用call來實現屬性的繼承。這種方式基本完美,但是我們發現構造方法Animal被調用2次,對于追求精益求精的我們,希望有更加完美的實現。

function Animal(age, name){
    this.Age = age;
    this.Name = name;
}

Animal.prototype.Eat = function(){
    console.log(this.Name + ' eat');
}

function Dog(species, age, name){
    this.Species = species;
    Animal.call(this, age, name);   //第二次調用Animal()
}

Dog.prototype = new Animal();  // 第一次調用Animal()

var dog = new Dog('博美', '5', 'Jim');
dog.Eat();
console.log(dog);

方法4:寄生組合繼承模式

屬性通過call, 方法通過原型鏈,但是這種方法不會調用2次Animal(), 這種方式去掉了Animal中多余的Age和Name屬性又完美的保留的與原型鏈。

// Object.create的非規范實現
function object(o) {
    function F() {}
    F.prototype = o;
    return new F();
}

function inheritPrototype(son, father) {
    var prototype = Object.create(father.prototype)
    // Object.create的實現參考上面的object

    prototype.constructor = son;
    // 通過Object.create生成的prototype沒有constructor, 
    // 所以要彌補son一個constructor

    son.prototype = prototype;
   

   // ES6 種引入了Object.setPrototypeOf, 可以省略上面的代碼直接用下面這行
   //Object.setPrototypeOf(son.prototype, father.prototype);
}

function Animal(age, name){
    this.Age = age;
    this.Name = name;
}

Animal.prototype.Eat = function() {
    console.log(this.Name + ' eat');
}

function Dog(species, age, name){
    this.Species = species;
    Animal.call(this, age, name);
}

inheritPrototype(Dog, Animal);

Dog.prototype.Cry = function(){
    console.log(this.Name + ' cry');
}

var dog = new Dog('博美', '5', 'Jim');
dog.Eat();
dog.Cry();

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 方法1:通過原型鏈 這種模式的問題是Dog的所有實例共享同一個Animal實例,一旦在dog1種修改Animal屬...
    強仔_5787閱讀 101評論 0 0
  • 本文先對es6發布之前javascript各種繼承實現方式進行深入的分析比較,然后再介紹es6中對類繼承的支持以及...
    lazydu閱讀 16,727評論 7 44
  • 繼承有什么作用? 繼承可以讓子類擁有父類的方法和屬性,然后在這個基礎上進行方法和屬性調用,可以提高代碼的復用性和效...
    柏龍閱讀 586評論 3 6
  • 在JS中繼承是一個非常復雜的話題,比其他任何面向對象語言中的繼承都復雜得多。在大多數其他面向對象語言中,繼承一個類...
    殖民_FE閱讀 201評論 0 2
  • //8.繼承 構造函數方式繼承 構造函數方式繼承的缺點:構造函數的方法會在實例化的時候多次執行,沒有必要。 原型方...
    一個廢人閱讀 76評論 0 2