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; } }; })();
本文导航
- 第1页: 首页
- 第2页: KLASS
- 第3页: 简单实现
- 第4页: mootools类库的Class