西西軟件下載最安全的下載網(wǎng)站、值得信賴的軟件下載站!

首頁編程開發(fā)javascript|JQuery → javascript面向?qū)ο蟀b類Class的類庫解析

javascript面向?qū)ο蟀b類Class的類庫解析

相關(guān)軟件相關(guān)文章發(fā)表評論 來源:pigtail時(shí)間:2013/1/22 14:42:29字體大。A-A+

作者:穆乙點(diǎn)擊:0次評論:0次標(biāo)簽: 面向?qū)ο?/a>

javascript是個(gè)入門門檻很低的語言,甚至一個(gè)從來沒有接觸過javascript的技術(shù)人員,幾小時(shí)內(nèi)就可以寫出一個(gè)簡單有用的程序代碼。

但是如果因此你就下結(jié)論:javascript是門簡單的語言。那你就大錯(cuò)特錯(cuò)了。想寫出高性能的代碼,同樣需要具備一個(gè)高級程序員的基本素養(yǎng)。

一個(gè)java或者c++程序員,不一定能寫出高性能的javascript代碼,但更容易寫出高性能的javascript代碼。

javascript的簡單是基于它“胸襟廣闊”的包容性。它聲明時(shí),不需要指定類型,甚至可以任意的轉(zhuǎn)換類型。它面向?qū)ο螅瑓s沒有類(Class)的限制。它是一門崇尚自由又非常嚴(yán)謹(jǐn)?shù)恼Z言,如果你是一個(gè)自由主義者,那么,擁抱javascript吧!

面向?qū)ο缶幊?(OOP) 是一種流行的編程方法。但javascript的OOP,較之JAVA、c++有很大的同,主要體現(xiàn)它的繼承方式不同。javascript是基于原型PROTOTYPE繼承的。所有對象都是基于原型鏈,最終追述到Object對象。

這里不想討論過多的關(guān)于javascript的繼承方式和其它語言的繼承方式的不同之處。主要討論如何封裝javascript的Class,以便更好的管理和維護(hù)基礎(chǔ)代碼,減少重復(fù)代碼,以及更好的模塊化編程。

下面是幾個(gè)github上找到的比較好的Class封裝類庫:

  一、MY-CLASS 

項(xiàng)目地址:https://github.com/jiem/my-class

先看基本用法:

a、新建一個(gè)類

(function() {
  // 新建類
  var Person = my.Class({
    // 添加靜態(tài)方法
    STATIC: {
      AGE_OF_MAJORITY: 18
    },
    // 構(gòu)造函數(shù)
    constructor: function(name, age) {
      this.name = name;
      this.age = age;
    },
    // 實(shí)例方法
    sayHello: function() {
      console.log('Hello from ' + this.name + '!');
    },
    // 實(shí)例方法
    drinkAlcohol: function() {
      this.age < Person.AGE_OF_MAJORITY ?
        console.log('Too young! Drink milk instead!') :
        console.log('Whiskey or beer?');
    }

  });
  // 暴露給命名空間
  myLib.Person = Person;

})();

var john = new myLib.Person('John', 16);
john.sayHello(); //log "Hello from John!"
john.drinkAlcohol(); //log "Too young! Drink milk instead!"

b、繼承一個(gè)類

(function() {

  //Dreamer 繼承 Person
  var Dreamer = my.Class(Person, {
    // 構(gòu)造方法
    constructor: function(name, age, dream) {
      Dreamer.Super.call(this, name, age);
      this.dream = dream;
    },
    // 實(shí)例方法
    sayHello: function() {
      superSayHello.call(this);
      console.log('I dream of ' + this.dream + '!');
    },
    // 實(shí)例方法
    wakeUp: function() {
      console.log('Wake up!');
    }

  });
  // Super訪問父類
  var superSayHello = Dreamer.Super.prototype.sayHello;
  // 暴露給全局命名空間
  myLib.Dreamer = Dreamer;

})();

var sylvester = new myLib.Dreamer('Sylvester', 30, 'eating Tweety');
sylvester.sayHello(); //log "Hello from Sylvester! I dream of eating Tweety!"
sylvester.wakeUp(); //log "Wake up!"

c、給類添加新方法

// 給myLib.Dreamer添加新方法
my.extendClass(myLib.Dreamer, {
  // 添加靜態(tài)方法
  STATIC : {
    s_dongSomeThing : function(){
        console.log("do some thing!");    
    }
  },
  // 添加實(shí)例方法
  touchTheSky: function() {
    console.log('Touching the sky');
  },
  // 添加實(shí)例方法
  reachTheStars: function() {
    console.log('She is so pretty!');
  }

});

d、實(shí)現(xiàn)一個(gè)類的方法

// 聲明一個(gè)新類
myLib.ImaginaryTraveler = my.Class({
  travel: function() { console.log('Traveling on a carpet!'); },
  crossOceans: function() { console.log('Saying hi to Moby Dick!'); }
});

(function() {

  //Dreamer 繼承 Person 實(shí)現(xiàn) ImaginaryTraveler的方法
  var Dreamer = my.Class(Person, ImaginaryTraveler, {
    // 構(gòu)造方法
    constructor: function(name, age, dream) {
      Dreamer.Super.call(this, name, age);
      this.dream = dream;
    }

   // ...

  });
  // 暴露給全局命名空間
  myLib.Dreamer = Dreamer;

})();

var aladdin = new Dreamer('Aladdin');
aladdin instanceof Person; //true
aladdin instanceof ImaginaryTraveler; //false
aladdin.travel();
aladdin.wakeUp();
aladdin.sayHello();

如果怕忘記new操作符

var Person = my.Class({

  //you can now call the constructor with or without new
  constructor: function(name, city) {
    if (!(this instanceof Person))
      return new Person(name, city);
    this.name = name;
    this.city = citye;
  }

});

下面看一下my.class的源代碼解析:

my.Class實(shí)現(xiàn)思路基本是這樣的,如果只有一個(gè)參數(shù),那么聲明的是一個(gè)基礎(chǔ)類,這個(gè)參數(shù)是用來聲明新類的方法和屬以及構(gòu)造函數(shù)。它不是繼承而來,但它可以被繼承。

繼承的思路,就是如果有兩個(gè)參數(shù),第一個(gè)參數(shù)做為父類被繼承,第二參數(shù)用來聲明新類的方法和屬性以及構(gòu)造函數(shù),它同樣可以被繼承。

如果有三個(gè)以上參數(shù)那么,除出第一個(gè)參數(shù)做為繼承的父類,最后一個(gè)參數(shù)用聲明新類的方法和屬性以及構(gòu)造函數(shù)。中間的參數(shù)是用類來擴(kuò)展新類的方法。當(dāng)然也可以通過my.extendClass擴(kuò)展新方法。

同時(shí),類庫為commonJS和瀏覽環(huán)境都提供了支持!

/*globals define:true, window:true, module:true*/
(function () {
  // Namespace object
  var my = {};
  // 保證AMD分模塊可用
  if (typeof define !== 'undefined')
    define([], function () {
      return my;
    });
  else if (typeof window !== 'undefined')
    // 保證客戶端可用
    window.my = my;
  else
    // 保證后臺可用
    module.exports = my;

  //============================================================================
  // @method my.Class
  // @params body:Object
  // @params SuperClass:function, ImplementClasses:function..., body:Object
  // @return function
  my.Class = function () {

    var len = arguments.length;
    var body = arguments[len - 1];    // 最后一個(gè)參數(shù)是指定本身的方法
    var SuperClass = len > 1 ? arguments[0] : null;     // 第一個(gè)參數(shù)是指繼承的方法,實(shí)例和靜態(tài)部分均繼承
    var hasImplementClasses = len > 2;    // 如果有第三個(gè)參數(shù),那么第二個(gè)就是implementClass,這里其實(shí)只繼承實(shí)例對象
    var Class, SuperClassEmpty;
    
    // 保證構(gòu)造方法
    if (body.constructor === Object) {
      Class = function() {};
    } else {
      Class = body.constructor;
      // 保證后面不覆蓋constructor
      delete body.constructor;
    }
    // 處理superClass部分
    if (SuperClass) {
      // 中間件實(shí)現(xiàn)實(shí)例屬性的繼承
      SuperClassEmpty = function() {};
      SuperClassEmpty.prototype = SuperClass.prototype;
      Class.prototype = new SuperClassEmpty();    // 原型繼承,解除引用
      Class.prototype.constructor = Class;    // 保證constructor
      Class.Super = SuperClass;    // 父對象訪問接口
      
      // 靜態(tài)方法繼承,重載superClass方法
      extend(Class, SuperClass, false);
    }
    
    // 處理ImplementClass部分,其實(shí)只繼承實(shí)例屬性部分,除SuperClass #arguments[0]# 和 body #arguments[length-1]#
    if (hasImplementClasses)
      for (var i = 1; i < len - 1; i++)
        // implement是繼承的實(shí)例屬性部分, 重載父對象implementClass方法
        extend(Class.prototype, arguments[i].prototype, false);    
    
    // 處理本身聲明body部分,靜態(tài)要STATIC指定,實(shí)例部分要?jiǎng)h除STATIC部分
    extendClass(Class, body);
    
    return Class;

  };

  //============================================================================
  // @method my.extendClass
  // @params Class:function, extension:Object, ?override:boolean=true
  var extendClass = my.extendClass = function (Class, extension, override) {
    // 靜態(tài)部分繼承靜態(tài)部分
    if (extension.STATIC) {
      extend(Class, extension.STATIC, override);
      // 保證實(shí)例部分不繼承靜態(tài)方法
      delete extension.STATIC;
    }
    // 實(shí)例屬性繼繼承實(shí)例部
    extend(Class.prototype, extension, override);
  };

  //============================================================================
  var extend = function (obj, extension, override) {
    var prop;
    // 其實(shí)這里的flase是表明,覆蓋父對象的方法
    if (override === false) {
      for (prop in extension)
        if (!(prop in obj))
          obj[prop] = extension[prop];
    } else {
       // 這里其實(shí)不覆蓋父對象的方法,包括toString
      for (prop in extension)
        obj[prop] = extension[prop];
      if (extension.toString !== Object.prototype.toString)
        obj.toString = extension.toString;
    }
  };

})();
              
              

        
    推薦文章

    沒有數(shù)據(jù)