JS的繼承

拖了好久的JS繼承終於來個總結了T^Tjavascript

本篇文章參考阮一峯老師的博文。一共有三篇。html

1、先說一下prototype對象java

function Cat(name, age){
    this.name = name;
    this.age = age;
    this.speak = function () {
        console.log(this.name + ' miao');
    }
}

var cat1 = new Cat('Tom', 1);
var cat2 = new Cat('John', 2);
console.log(cat1.speak());    // Tom miao
console.log(cat2.speak());    // John miao

上面代碼中的兩個實例,cat1 和 cat2 都有本身的name屬性,age屬性,speak方法,可是其實speak方法實能夠共用的,這樣就會形成了資源浪費。避免這種浪費,咱們能夠把 speak 方法寫入構造函數的 prototype 對象中。app

function Cat(name, age){
    this.name = name;
    this.age = age;
}

Cat.prototype.speak = function(){
    console.log(this.name + ' miao');
}

var cat1 = new Cat('Tom', 1);
var cat2 = new Cat('John', 2);

將能夠共享的方法掛載在原型對象上,就能夠避免出現內存浪費的現象了函數

Cat.prototype.speak = function() {
    console.log(this.name + ' miao');
}

Cat.prototype.eat = 'fish';

cat2.prototype.eat = 'meat';


// 問題來了,若是我改變其中一個實例的原型上的屬性和方法,那麼另外一個原型會不會收到影響呢

答案是不會!!!this

 

 

 可是,若是修改的是 cat2.__proto__.eat,那麼就會對 cat1 有影響了spa

 

 

 這裏可能有點迷!!!是的,我有點迷~~~~~~~prototype

我是這樣子理解的3d

由於建立實例須要用到 new 操做符,那麼 new 中間做了什麼妖呢code

  • 建立了一個新對象
  • 將新對象的__proto__屬性指向構造函數的原型對象,新對象就新增了構造函數原型對象上的屬性和方法
  • 將構造函數的this指向替換成新對象,再執行構造函數,這樣新對象就新增了構造函數本地的屬性和方法了
    // 模擬 new
    var obj = {};
    obj.__proto__ = 構造函數.prototype;
    構造函數.apply(obj);

     

那麼看會又來的構造函數 Cat,我畫了這樣一幅圖

 

 

2、JS繼承

  1. 原型鏈繼承——將父類的實例做爲子類的原型
    function Animal(name){
        this.name = name;
    }
    Animal.propotype = {
        canRun: function(){
            console.log(this.name + ' can run.');
        }
    }
    function Cat(){
        this.speck = 'miao';
    }
    Cat.prototype = new Animal('Tom');
    Cat.prototype.constructor = Cat;

    我以爲應該會有人有和我同樣的疑惑。爲何會有Cat.prototype.constructor = Cat的出現。

     由於咱們把父類Animal的實例做爲了子類Cat的原型對象,所以若是沒有Cat.prototype.constructor = Cat,Cat.prototype.constructor就會指向Animal,形成繼承鏈的混亂,因此咱們須要手動糾正。

    2. 構造繼承——改變this的指向,用apply或者call方法實現

    

function Animal(name){
    this.name = name;
}
Animal.prototype = {
    canRun: function(){
        console.log(this.name + ' it can run!');
    }
}
function Cat(name){
    Animal.call(this, name);
    this.speak = 'miao';
}
var cat1 = new Cat('Tom');

    這個繼承方法有一個很差,就是子類沒法繼承父類原型上的屬性和方法,也就是說 cat1.canRun()會出錯。

 

 

         3. 組合繼承——將原型鏈繼承和構造繼承結合到一塊

    

function Animal(name){
    this.name = name;
}
Animal.prototype = {
    canRun: function(){
        console.log(this.name + 'is can run!');
    }
}
function Cat(name, age){
    Animal.call(this, name);
    this.speak = 'miao';
    this.age = age;
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
var cat1 = new Cat('Tom', 12);
相關文章
相關標籤/搜索