拖了好久的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
// 模擬 new var obj = {}; obj.__proto__ = 構造函數.prototype; 構造函數.apply(obj);
那麼看會又來的構造函數 Cat,我畫了這樣一幅圖
2、JS繼承
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);