2-JavaScript設計模式——commonUtils工具庫之繼承函數

在學習 JavaScript 設計模式之前,我們先做一個 commonUtils 工具庫,以便於後期的學習和使用。


 commonUtils 工具庫包括:多維數組遍歷,繼承函數,接口類及其驗證。


本章爲繼承函數:

☞ 繼承的實現

// 繼承的實現包含以下步驟
// 定義一個父類的模板(構造器)
function Sup(name, age){
  this.name = name;
  this.age = age;
}

// 爲父類添加原型方法
Sup.prototype = {
  /*
    注意:這裏一定要重新定義構造器
      因爲 {} 代表的是一個單體對象,其構造器爲Object,所以需要重新定義構造器爲Sup;
      但實際開發中,經常會有忘記重新定義構造器,我們將在繼承函數中規避這一問題。
  */
  constructor : Sup,
  eat : function(){
    alert(this.name + ' 正在喫飯...');
  },
  sleep : function(){
    alert(this.name + ' 正在睡覺...');
  }
};

// 定義一個子類的模板
// 注意:父類傳遞的參數,子類也要傳遞
function Sub(name, age, sex){
  // 繼承父類的模板,即 將父類的模板綁定到子類的模板的作用域中
  Sup.call(this, name, age);
  this.sex = sex;
}

/*
  1、讓子類繼承父類,即 讓子類的原型對象 等於 父類的實例,於是 子類同時繼承了父類的模板和原型對象。
  2、父類實例不能傳參,否則子類所繼承自父類的屬性就被固化了。
  3、這樣存在一個問題,這裏繼承一次父類模板,子類作用域中又繼承了一次父類模板,一共繼承了兩次,如果父類屬性成員較多,則會影響性能,我們將在繼承函數中解決這一問題。
*/
Sub.prototype = new Sup(); 
/*
 構造函數 原型對象 實例對象 之間的關係
  1、構造函數.prototype = 原型對象
  2、原型對象.constructor = 構造函數(模板)
  3、原型對象.isPrototypeOf(實例對象) 判斷實例對象的原型 是不是當前對象
  4、構造函數 <=> 實例對象 (類和實例)
*/


☞ 繼承函數

// 命名空間
var JG = {};

// 繼承函數。 傳參:sub 子類;sup 父類。
JG.extend = function(sub, sup){
  // 創建一箇中間類 F
  function F(){}
  
  F.prototype = sup.prototype;
  
  /*
    讓子類繼承中間類 F, 這樣子類繼承了 中間類的構造器(空的模板)和原型對象,解決了 兩次繼承父類模板問題 對性能的影響
  */
  sub.prototype = new F();
  
  // 將子類的構造器 改回 子類本身
  sub.prototype.constructor = sub;
  
  // 爲子類定義一個 superClass 屬性,值爲父類的原型對象,這樣在子類中可以通過調用 superClass 屬性來代替父類的原型對象,從而實現解耦的目的。
  sub.superClass = sup.prototype;
  
  // 如果父類構造器爲,Object,則更改爲 父類本身,從而解決 忘記重新定義構造器問題。
  if(sup.prototype.constructor === Object.prototype.constructor){
    sup.prototype.constructor = sup;
  }
};

// 測試
// 父類
function Person(name, age){
  this.name = name;
  this.age = age;
}

// 父類原型對象
Person.prototype = {
  constructor : Person,
  eat : function(){
    alert(this.name + ' 正在喫飯...');
  },
  sleep : function(){
    alert(this.name + ' 正在睡覺...');
  }
};

// 子類
function Student(name, age, sex){
  // 繼承父類模板
  Student.superClass.constructor.call(this, name, age);
  this.sex = sex;
}

// 繼承
JG.extend(Student, Person);

// 擴展子類原型對象 注意:必須寫在繼承後面,否則會被重置清空
Student.prototype.study = function(){
  alert(this.name + ' 正在學習...');
};

// 實例
var zhangSan = new Student('zhangSan', 18, '男');

document.write(zhangSan.name + ': ' + zhangSan.age + ', ' + zhangSan.sex + '<br><br>');//zhangSan: 18, 男
zhangSan.eat(); // zhangSan 正在喫飯...
zhangSan.sleep(); // zhangSan 正在睡覺...
zhangSan.study(); // zhangSan 正在學習...


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章