設計模式什麼的根本記不住啊 , 直接看各種原生JS繼承吧!!!

原生JS繼承詳解

參考資料
不要講什麼設計模式 , 看得老子腦袋昏 , 智商欠費 , 仍是簡單點 , 方案 , 繼承 , 就完事了html

// 首先咱們得有個父類
// 這個父類也很簡單
function Human(name) {
    this.name = name || '肥宅' // 有參就取參 , 沒參就叫肥宅
}
Human.prototype.drink = function(drinks) {
    console.log(this.name + '正在喝' + (drinks || '可樂'));
}
複製代碼

OK, 咱們如今有了一個父類, 先來看一個最簡單的繼承設計模式

最簡單的原型鏈繼承

直接把父類的實例做爲子類的原型函數

// 先寫個空類
function Jianren(){}
Jianren.prototype = new Human()

// new個實例看看
var haidong = new Jianren();

console.log(haidong.name); //'肥宅'
console.log(haidong.drink()); //'haidong正在喝可樂'
複製代碼

對於這個繼承, 歸納爲子類的原型鏈綁定父類的實例實現繼承性能

缺陷ui

  1. 不能實現多類繼承
  2. 爲子類新增屬性和方法,必需要在new Animal()這樣的語句以後執行
  3. 沒法控制子類可以訪問父類屬性的權限
  4. 建立子類的實例時也不能向父類構造函數傳參

構造繼承

複製父類屬性this

function Jianren(){
  Human.call(this);// 把父類寫進子類構造函數內部, 調用call把子類的this傳進去改變this的指向作到複製父類屬性
  this.age = 22
}
複製代碼
  1. 構造繼承其實就是複製了父類屬性, new Jianren()出來的實例的construct和prototype都與Human無關, 指向Jianren()
  2. 能夠無論new 父類先後順序來新增子類的屬性
  3. 建立子類實例時, 也能夠向父類傳遞參數,
  4. 能夠call多個父類實現多類繼承
  5. 只能繼承父類的實例屬性和方法, 不能繼承/訪問到父類原型上的東西
  6. 難以複用, 影響性能

實例繼承

在子類內部添加一個屬性, 該屬性爲父類的實例spa

function Jianren(name){
  var ren = new Human();// 注意這裏是否是this
  ren.name = name || 'haidong';
  return ren;
}
複製代碼
  1. 不會限制調用的方式, new 子類() 或者 子類()執行, 都返回ren
  2. new Jianren()的實例其實是new Human(), constructor也是指向Human()
  3. 不支持多類繼承

拷貝繼承

function Jianren(name){
  var ren = new Human()
  for(var r in ren) {
      Cat.prototype[r] = ren[r] // 該處r是key, 應該用Object[key]的形式賦值和訪問
  }
  Jianren.prototype.name = name || 'haidong'
}
複製代碼
  1. 支持多繼承
  2. 效率低, 拷貝屬性會佔用內存
  3. 不可枚舉父類

推薦的兩種繼承

組合繼承和寄生組合繼承

上面的繼承主要是幫助理解, 或有時暴力快速解決小問題時使用 .prototype

推薦一, 組合繼承設計

子類的原型指向父類實例,該父類實例又可向上原型查找訪問,修正後constructor指向子類自身code

function Jianren(name) {
    Human.call(this) //第一步拷貝屬性
    this.name = name || 'haidong'
}
Jianren.prototype = new Human() //第二步, 原型指向父類實例
Jianren.prototype.constructor = Jianren //第三步, 修正constructor指向
複製代碼
  1. 能夠繼承實例的屬性/方法, 也能夠繼承原型的屬性方法,
  2. 是子類的實例, 也至關因而父類的實例
  3. 子類的原型指向父類實例,該父類實例又可向上原型查找訪問,修正後constructor指向子類自身
  4. 可傳參,//call()能夠傳參,具體用法,自行百度谷歌
  5. 調用兩次父類構造函數, 佔內存, 第一步拷貝過一次, 第二步致使之後的Jianren的實例裏和Jianren原型上重複的屬性

推薦二, 寄生組合繼承

// 有點複雜
function Jianren(name) {
    Human.call(this) //第一步拷貝屬性
    this.name = name || 'haidong'
}
(function() { //來個匿名當即執行函數
    function J() {}// 建立一箇中間類, 空, 什麼都沒有
    J.prototype = Human.prototype //第二步中間類原型指向父類原型
    Jianren.prototype = new J() //子類原型賦值爲中間類的實例,往上查找,指向了父類的原型
})()
Jianren.prototype.constructor = Jianren //修正子類constructor指向
複製代碼

與上面的組合繼承相比, 第一步拷貝 和 第二步中間類(空類)不會重複有Human的屬性, 略微複雜, 能夠忽略不計, 完美方式

相關文章
相關標籤/搜索