西西软件下载最安全的下载网站、值得信赖的软件下载站!

首页编程开发javascript|JQuery → javascript面向对象包装类Class的类库解析

javascript面向对象包装类Class的类库解析

相关软件相关文章发表评论 来源:pigtail时间:2013/1/22 14:42:29字体大小:A-A+

作者:穆乙点击:0次评论:0次标签: 面向对象

javascript是个入门门槛很低的语言,甚至一个从来没有接触过javascript的技术人员,几小时内就可以写出一个简单有用的程序代码。

但是如果因此你就下结论:javascript是门简单的语言。那你就大错特错了。想写出高性能的代码,同样需要具备一个高级程序员的基本素养。

一个java或者c++程序员,不一定能写出高性能的javascript代码,但更容易写出高性能的javascript代码。

javascript的简单是基于它“胸襟广阔”的包容性。它声明时,不需要指定类型,甚至可以任意的转换类型。它面向对象,却没有类(Class)的限制。它是一门崇尚自由又非常严谨的语言,如果你是一个自由主义者,那么,拥抱javascript吧!

面向对象编程 (OOP) 是一种流行的编程方法。但javascript的OOP,较之JAVA、c++有很大的同,主要体现它的继承方式不同。javascript是基于原型PROTOTYPE继承的。所有对象都是基于原型链,最终追述到Object对象。

这里不想讨论过多的关于javascript的继承方式和其它语言的继承方式的不同之处。主要讨论如何封装javascript的Class,以便更好的管理和维护基础代码,减少重复代码,以及更好的模块化编程。

下面是几个github上找到的比较好的Class封装类库:

  一、MY-CLASS 

项目地址:https://github.com/jiem/my-class

先看基本用法:

a、新建一个类

(function() {
  // 新建类
  var Person = my.Class({
    // 添加静态方法
    STATIC: {
      AGE_OF_MAJORITY: 18
    },
    // 构造函数
    constructor: function(name, age) {
      this.name = name;
      this.age = age;
    },
    // 实例方法
    sayHello: function() {
      console.log('Hello from ' + this.name + '!');
    },
    // 实例方法
    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、继承一个类

(function() {

  //Dreamer 继承 Person
  var Dreamer = my.Class(Person, {
    // 构造方法
    constructor: function(name, age, dream) {
      Dreamer.Super.call(this, name, age);
      this.dream = dream;
    },
    // 实例方法
    sayHello: function() {
      superSayHello.call(this);
      console.log('I dream of ' + this.dream + '!');
    },
    // 实例方法
    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, {
  // 添加静态方法
  STATIC : {
    s_dongSomeThing : function(){
        console.log("do some thing!");    
    }
  },
  // 添加实例方法
  touchTheSky: function() {
    console.log('Touching the sky');
  },
  // 添加实例方法
  reachTheStars: function() {
    console.log('She is so pretty!');
  }

});

d、实现一个类的方法

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

(function() {

  //Dreamer 继承 Person 实现 ImaginaryTraveler的方法
  var Dreamer = my.Class(Person, ImaginaryTraveler, {
    // 构造方法
    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实现思路基本是这样的,如果只有一个参数,那么声明的是一个基础类,这个参数是用来声明新类的方法和属以及构造函数。它不是继承而来,但它可以被继承。

继承的思路,就是如果有两个参数,第一个参数做为父类被继承,第二参数用来声明新类的方法和属性以及构造函数,它同样可以被继承。

如果有三个以上参数那么,除出第一个参数做为继承的父类,最后一个参数用声明新类的方法和属性以及构造函数。中间的参数是用类来扩展新类的方法。当然也可以通过my.extendClass扩展新方法。

同时,类库为commonJS和浏览环境都提供了支持!

/*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];    // 最后一个参数是指定本身的方法
    var SuperClass = len > 1 ? arguments[0] : null;     // 第一个参数是指继承的方法,实例和静态部分均继承
    var hasImplementClasses = len > 2;    // 如果有第三个参数,那么第二个就是implementClass,这里其实只继承实例对象
    var Class, SuperClassEmpty;
    
    // 保证构造方法
    if (body.constructor === Object) {
      Class = function() {};
    } else {
      Class = body.constructor;
      // 保证后面不覆盖constructor
      delete body.constructor;
    }
    // 处理superClass部分
    if (SuperClass) {
      // 中间件实现实例属性的继承
      SuperClassEmpty = function() {};
      SuperClassEmpty.prototype = SuperClass.prototype;
      Class.prototype = new SuperClassEmpty();    // 原型继承,解除引用
      Class.prototype.constructor = Class;    // 保证constructor
      Class.Super = SuperClass;    // 父对象访问接口
      
      // 静态方法继承,重载superClass方法
      extend(Class, SuperClass, false);
    }
    
    // 处理ImplementClass部分,其实只继承实例属性部分,除SuperClass #arguments[0]# 和 body #arguments[length-1]#
    if (hasImplementClasses)
      for (var i = 1; i < len - 1; i++)
        // implement是继承的实例属性部分, 重载父对象implementClass方法
        extend(Class.prototype, arguments[i].prototype, false);    
    
    // 处理本身声明body部分,静态要STATIC指定,实例部分要删除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) {
    // 静态部分继承静态部分
    if (extension.STATIC) {
      extend(Class, extension.STATIC, override);
      // 保证实例部分不继承静态方法
      delete extension.STATIC;
    }
    // 实例属性继继承实例部
    extend(Class.prototype, extension, override);
  };

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

})();
              
              

        

    相关评论

    阅读本文后您有什么感想? 已有人给出评价!

    • 8 喜欢喜欢
    • 3 顶
    • 1 难过难过
    • 5 囧
    • 3 围观围观
    • 2 无聊无聊

    热门评论

    最新评论

    发表评论 查看所有评论(0)

    昵称:
    表情: 高兴 可 汗 我不要 害羞 好 下下下 送花 屎 亲亲
    字数: 0/500 (您的评论需要经过审核才能显示)
    推荐文章

    没有数据