cu_Cbear 发表于 2012-01-10 16:35

Mootools类定义增强因子

Mootools类定义增强因子






最近研习《Pro Javascript with Mootools》,跟jQuery比起来,Mootools的资料算是少之又少的(Mootools在用户推广和社区建设方面有必要向jQuery学习下)。这本书比较全面的对Mootools-core中各个关键模块做了说明和分析,每章都由原生javascript逐渐引入,总之是本不错的书,虽然现在jQuery在业界大红大紫, 但个人也希望mootools能得到不错的发展。

回到正题,Mootools跟jQuery一个比较显著的差异就是在代码组织方式上,Mootools引入了OOP思想,实现了功能强大的Class类。

Mootools默认内置了两个Class的增强因子,一个是Extends,另外一个是Implements.

有一定Mootools使用经验的园友应该很熟悉这两个扩展,内部都用于实现javascript的prototype链继承(但是不仅仅如此)。

不同的是Extends模拟OOP中子类继承父类的操作,Implements的话可以理解成继承方法(和Java或者C#中实现接口有些不同,接口只是函数声明,没有定义)。

下面个例子:?12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 var Human = new Class({   // 初始化方法   initialize: function(name, gender) {         this.name = name;         this.gender = gender;   },         toString: function() {         return 'name:' + this.name + ',' + 'gender:' + this.gender;   }   });   var Behavior = new Class({       eat: function() {         console.log(this.name + ' wanna grab something to eat');   },         sleep: function() {         console.log(this.name + ' wanna sleep');   },         haveFun: function() {         console.log(this.name + ' wanna have some fun');   }   });   var Developer = new Class({         Extends: Human,         Implements: Behavior,         initialize: function(name, gender, lang) {         this.parent(name, gender); //调用父类中对应的方法         this.lang = 'javascript';   },         toString: function() {         return this.parent() + ',language:' + this.lang;   } });   var Andrew = new Developer('Andrew', 'male', 'javascript');console.log(Andrew.toString()); // name:Andrew,gender:male,language:javascript Andrew.eat();                   // Andrew wanna grab something to eat Andrew.sleep();               // Andrew wanna sleep Andrew.haveFun();               // Andrew wanna have some fun 从这个例子出应该不难看出Extends和Implements所起到的作用,如果你像我一样对其中的实现细节很感兴趣,可以研究下Mootools中的Class模块,一开始去看源码确实有点困难,硬着头皮多看几遍就慢慢有点思路了。这里有篇园友的随笔,他对Class模块做了一些注释,足够了解其运行机制。点击浏览此文,感谢苦苦的苦瓜。

除了基本的Extends和Implements,我们还可以实现自定义的增强因子,从源码中我们可以看出,Class模块的增强因子通过Class.Mutators进行扩展。下面给出源码,我们可以有个参照。?1234567891011121314 Class.Mutators = {       Extends: function(parent){         this.parent = parent;         this.prototype = getInstance(parent);   },       Implements: function(items){         Array.from(items).each(function(item){             var instance = new item;             for (var key in instance) implement.call(this, key, instance, true);         }, this);   } }; 一下子看不大明白很正常,如果要分析源码,篇幅会很长,这里其实只要搞清一些注意点就行. 结合之前的Developer例子看,Class.Mutators.Extends执行时,其中this指的就是构造类Developer(记得吗,我们通过new Developer来产生一个实例),其中parent就是继承的Human构造类,getInstance(parent)返回Human的实例,这里很明显就是基于prototype的继承实现(但不仅如此,就这块代码而言是这样)。再简单的看下Class.Mutators.Implements,运行时通过其中的implement方法给Developer的prototype扩展方法或属性。

现在来个自定义的例子,我们自己动手干, 来实现一个自动实现属性getter,setter方法:
?12345678910111213141516 // mootools Mutator GetterSetter         Class.Mutators.GetterSetter = function(props) {             var klass = this;             Array.from(props).each(function(prop) {               var capProp = prop.capitalize();                                 klass.implement('set' + capProp, function(value) {                     this = value;                     return this;               });                                 klass.implement('get' + capProp, function(value) {                     return this;               });             });         }; 如果我们把GetterSetter用于Developer构造类的定义,那么Class.Mutators.GetterSetter执行时,this指的就是Developer。我们看一下each里面的回调,通过闭包klass维持着对Developer的引用,通过implement方法在其prototype上扩展属性的setter,getter方法。这样Developer的实例就自动拥有了类似Java类中的setter,getter。通过扩展Class.Mutators,我们优雅的实现了这个功能。来验证一下:
?12345678910111213141516171819202122 var Developer = new Class({                   Extends: Human,                   Implements: Behavior,                   GetterSetter: ['name', 'gender', 'lang'],                   initialize: function(name, gender, lang) {             this.parent(name, gender);             this.lang = 'javascript';         },                   toString: function() {             return this.parent() + ',language:' + this.lang;         }   });      var Andrew = new Developer('Andrew', 'male', 'javascript');   console.log(Andrew.getName());    // Andrew   console.log(Andrew.getGender());// male   console.log(Andrew.getLang());    // javascript个人觉得很强大,再来一个实现模拟静态属性(static)的例子:

?123 Class.Mutators.Static = function(props) {   this.extend(props); };
看起来再简单不过了,不是么?我们再来验证一下:?12345678910111213141516171819202122232425262728 var Developer = new Class({         Static: {             count: 0,                           addCount: function() {               Developer.count++;             }         },                   Extends: Human,                   Implements: Behavior,                   initialize: function(name, gender, lang) {             this.parent(name, gender);             this.lang = 'javascript';                           Developer.addCount();         },                   toString: function() {             return this.parent() + ',language:' + this.lang;         }   });      var Andrew = new Developer('Andrew', 'male', 'javascript');   var Rocky = new Developer('Rocky', 'male', 'php');   console.log(Developer.count); //2
我们通过count给实例化的对象计数,或许你会觉得count和addCount就这么暴露给外部是个问题,我们可以用匿名函数来模拟实现private:?12345678910111213141516171819202122232425262728293031323334353637 var Developer = (function() {                           // private variable or function             var count = 0,                   addCount = function() {                     count++;               };                           return new Class({               Static: {                        getCount: function() {                         return count;                     }               },                                 Extends: Human,                                 Implements: Behavior,                                 initialize: function(name, gender, lang) {                     this.parent(name, gender);                     this.lang = 'javascript';                                           addCount();               },                                 toString: function() {                     return this.parent() + ',language:' + this.lang;               }             });         })();         var Andrew = new Developer('Andrew', 'male', 'javascript');         var Rocky = new Developer('Rocky', 'male', 'php');         console.log(Developer.count);      // undefined               console.log(Developer.addCount());   // undefined         console.log(Developer.getCount()); // 2
注意到,我们利用匿名函数和闭包特性模拟实现了count和addCount的private,对比之前外部可以通过Developer.count或者Developer.addCount直接改变计数显得安全的多了。

最后就jQuery和Mootools,我想再稍微吐糟一下。

jQuery为何如此流行:它起点低,入门简单,不怎么懂javascript的程序员或者设计师,都可以简单上手,而且它的文档做的很不错,用户推广做的好,社区活跃,不可否认jQuery形势一片大好,在结合BackBone等MVC framework的辅助,真是不错。

Mootools虽然几乎和jQuery同时出现,但是其社区规模和受欢迎程度确实没有jQuery高,从github上watch和fork人数就可见一斑。一方面Mootools的上手确实不太适合javascript初学者,另一方面对于很多程序员来讲,貌似并不需要Mootools的对OOP的实现,而jQuery对于DOM操作和特效的实现更为简单...所以,Mootools现在的情况有点小尴尬,不过它依然是一个很好的framework。希望也能很好的发展。

蓝猫淘气啦啦 发表于 2012-01-10 16:35

看看
页: [1]
查看完整版本: Mootools类定义增强因子