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:組合繼承模式

這種方法結(jié)合了方法1和方法2。用原型鏈實現(xiàn)方法的繼承,在構(gòu)造函數(shù)中實用call來實現(xiàn)屬性的繼承。這種方式基本完美,但是我們發(fā)現(xiàn)構(gòu)造方法Animal被調(diào)用2次,對于追求精益求精的我們,希望有更加完美的實現(xiàn)。

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);   //第二次調(diào)用Animal()
}

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

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

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

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

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

function inheritPrototype(son, father) {
    var prototype = Object.create(father.prototype)
    // Object.create的實現(xiàn)參考上面的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();

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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

友情鏈接更多精彩內(nèi)容