龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > web编程 > Javascript编程 >

jQuery与MooTools库的一些比对(1)

时间:2013-03-06 14:58来源:未知 作者:admin 点击:
分享到:
我上大学那会儿从事的项目用的是jQuery,毕业后工作所从事的项目用的是MooTools。很幸运短期内有机会接触两款不同设计风格的优秀的JavaScript库。今天就我自己的一些认识比对下这两个

我上大学那会儿从事的项目用的是jQuery,毕业后工作所从事的项目用的是MooTools。很幸运短期内有机会接触两款不同设计风格的优秀的JavaScript库。今天就我自己的一些认识比对下这两个JS框架,更多的是希望大家能够对MooTools这个JS框架有更多的认识。毕竟,大多数从事web前端的人对上手容易的jQuery更熟悉些。

51CTO推荐专题:jQuery从入门到精通

一、API设计

就API的设计上来讲,无论是MooTools,或是其他类似YUI的JS框架都比jQuery略逊一筹。

API是什么?根据某些著作的回答,API是对所需知识的抽象,它将系统的复杂性隐藏起来。例如汽车的方向盘,电视机上的按钮。一个API设计的好坏可以从下面几个方面评估:可理解性、一致性、预见性、简单性、保护性。

◆ 可理解性

例如selector(选择器)。随便举个选择器的例子(jQuery):

  1. $("#jQuery div"

选择器的写法是与CSS的选择器是一脉相承的。因此对于很多写页面的人来讲,可以很轻松地使用jQuery找到自己想要的那根葱。jQuery后来的版本之所以把XPath干掉,或许就是因为理解性上的问题吧。当然,MooTools也是支持CSS选择器的,只不过,其不是使用一个美元符号$,而是两个$$,貌似是学习prototype框架,返回的是数组。

  1. $$("#MooTools div"

如果MooTools只走到这一步,我觉得还好,貌似跟jQuery的可理解性打个小平手。只可惜,MooTools还有一个单个美元符号$的选择器,其中参数只能是元素的id,例如:

  1. $("MooTools"

这玩意,选择的貌似是有个MooTools元素扩展方法的对象。如果不存在,应用元素方法的时候(eg: addClass)则会报错。

也就是说MooTools选择元素,根据用法的不同,有时候返回的可能就是数组,有时候又是元素对象。这难免让对JS熟悉,对CSS较熟悉的人员有了理解和使用上的困难了。不过这不能怪MooTools,设计架构上的不同导致MooTools有时候需要返回元素对象,而不是元素对象数组。

因此,从理解性上来说,MooTools逊于jQuery了。

◆ 一致性

JS框架的一致性的主要体现之一就是链式调用,例如(jQuery):

  1. $("#jQuery").css("color""red").height(200); 

MooTools也是支持链式调用的,例如(MooTools):

  1. $$("#MooTools").setStyle("color""red").setStyle("height", 200); 

在链式调用上,jQuery和MooTools基本上都是很OK的。

但是,在其他方面的一致性上,MooTools似乎又落于下风了。jQuery这个框架真的很神奇,一个$符号就可以从广州走到北京,真可谓万能密匙啊。

首先选择器,例如$("#jQuery")肯定是$符号,然后,其相关的其他些方法,例如插件机制之$.fn.extend(object),或者是Ajax请求$.ajax([options]),又或是浏览器检测,数组对象方法等等等等都是$符号横行的。

但是,MooTools桑中$符号出现在选择器,让人难懂的$A, $E,以及一些公共方法命名上,其余时候都回家睡觉觉了。

继承需要new Class()构造,Ajax请求为new Request([options]),然后浏览器检测又是以Browser开头。数组,字符串等方法又都是当前对象本身打头,如myString.trim()。毫无一致性可言,显然,这个的学习成本和使用难度要比jQuery大多了。

◆ 预见性

好的API应该考虑到用户的无绪性选择(selective cluelessness)以及预见未来可能发生的一些事情。

不知是John Resig(jQuery 之父)确实想的很远,还是因为幸运,或是只因为John是个天才,jQuery的设计让其似乎不会与未来发生冲突。

举个老到啃不动的例子,过滤字符串的前后空格。jQuery的做法是:

  1. $.trim(myString); 

MooTools做法是:

  1. myString.trim(); 

乍一看,似乎MooTools框架的做法更符合我们的理解 → 字符串对象有个trim方法,返回过滤前后空格的字符串方法。However,随着时间拖移,有些事情就开始发生变数了。

在ECMAScript 5(ES5)中,字符串是内置trim方法的。我们可以做个小小的测试,如下代码:

  1. alert((" foo ").trim()); 

您可以狠狠地点击这里:ES5 内置trim方法测试

例如,在我的FireFox 6浏览器下,弹出的就是foo,如下截图:

FireFox 6 弹出foo

对于一些有历史价值的浏览器,就不支持,例如IE7模式下:

同样类似的就是基于Function扩展的bind方法,MooTools中有,但是,ES5中也内置了。只是,比较幸运的是,无论是字符串trim方法,或是函数bind方法,虽然名称冲突了,但是,所实现的功能确是一样的,因此,也算不上冲突了。但是,万一哪天遇到个不幸,MooTools中的某个方法与ES5中的方法同名但不同功能,然后,只能老泪纵横了!

再举个预见性的例子,选择器选择对象以及DOM对象。jQuery对jQuery对象和原生dom对象进行了分离,例如:

  1. $("input").bind("focus"function() {  
  2.     alert(this.value);      // dom对象  
  3.     alert($(this).val());   // jQuery包装器对象  
  4. }); 

但是,在MooTools中,一些方法是在原生DOM上扩展的,MooTools元素对象和原生dom是合体的,例如:

  1. $$("input").addEvent("focus"function() {  
  2.     alert(this.value);           // dom对象  
  3.     alert(this.get("value"));    // 扩展后的dom对象  
  4. }); 

“合体”的问题在于随着浏览器以及一些规范的发展,原生dom可能会支持其他的一些方法,这些方法有可能就和MooTools插件中DOM扩展方法冲突。好在MooTools的方法命名属于对称命名,且语义明显,这种设计可以有效避免与原生dom方法的冲突。但是,事情没有这简单……下面你可以看到MooTools中DOM元素方法的设计的一些问题(当然,不可否认,这种设计使用上相对灵活些)。

简单性

jQuery之所以让开发者恋恋不舍,原因之一就是其简单。jQuery的口号就是"write less, do more."

拿dom-style的API举例,MooTools, YUI等框架采用的是传统对称命名的方式(prop为property属性缩写):

  1. el.setStyle(prop, val);  
  2. el.getStyle(prop);  
  3. el.setStyles({ propA: valA, propB: valB });  
  4. el.getStyles(propA, propB);   // MooTools支持, 返回是个名-值对象 

在jQuery里,一个CSS就把所有瓷器活都揽了:

  1. el.css(prop);    // 表示 getStyle  
  2. el.css(prop, val);    // 表示 setStyle  
  3. el.css({ propA: valA, propB: valB });    // 表示 setStyles   
  4. el.css(prop, func);    // func 是一个返回 val 值的函数    

虽然参数类似,但是jQuery只要记一个名字,而MooTools却要N个,且名字也比较长(必须完整且长,否则易出问题)。这也是为什么jQuery更容易上手的原因。而且,jQuery更近一步,还支持func回调,且参数可以map, val可以是函数,暗藏多多surprise啊。

显然,简单性这块又是jQuery好一些。

这里,我还想说点其他相关的东西。jQuery框架的短命名设计确实好,于是我就想对MooTools的元素方法进行扩展,使等同于jQuery的命名书写方式,一是省些代码,二是方便熟悉jQuery的新员工上手,拿还是上面dom-style的例子,MooTools如下扩展处理:

  1. Element.implement({  
  2.     //将mootools默认的setStyle以及setStyles方法转化为与jQuery类似的css()形式  
  3.     css: function(key, value) {  
  4.         if ($type(key) == 'object') {  
  5.             for (var p in key) this.css(p, key[p]);  
  6.             return this;  
  7.         }  
  8.         if(!$chk(value)){  
  9.             return this.getStyle(key);  
  10.         }  
  11.         this.setStyle(key, value);  
  12.         return this;  
  13.     }  
  14. }); 

于是,MooTools也支持CSS方法,例如可以直接$("mootools").css({ border: "1px solid #ddd" });。恩,看上去不错,确实,上面的扩展在目前各个浏览器中是没有任何问题的。于是,初尝到了甜头,我们就想模拟其他jQuery包装器方法的扩展,例如width/height方法,如下(width举例):

  1. Element.implement({  
  2.     width: function (val) {  
  3.         if ($chk(val)) {  
  4.             return this.setStyle("width", val);  
  5.         } else {  
  6.             return this.getWidth();  
  7.         }  
  8.     }  
  9. }); 

看上去不错,不是吗?但是,人生不如意事八九,上面MooTools框架对dom进行的width方法扩展是有问题的。我们都知道,<img>元素是有width属性的。正如上面提到的,MooTools框架的元素方法是在DOM上面直接“合体”扩展的。于是乎,对于图片而言,使用上面扩展的width方法是会嗝屁的——原生属性与扩展方法冲突。

  1. alert($("image").width()); //报错,显示$("image").width不是function 

由此又进一步证实了jQuery在API设计上更能避免一些当下或未来潜在的冲突,更具远见性。

保护性

jQuery有个多库共存机制,可以有效地保护其他框架都在争夺的$符号,有效避免了一些兼容性的问题。

  1. jQuery.noConflict();  
  2. (function($) {  
  3.   $(function() {  
  4.     // 使用 $ 作为 jQuery 别名的代码  
  5.   });  
  6. })(jQuery);  
  7. // 其他用 $ 作为别名的库的代码 

而MooTools中似乎并无这样的机制。

总结:就API设计这点来讲,jQuery几乎从各个方面都强于MooTools,这也是jQuery大行其道的主要原因。

二、性能

◆ 选择器性能

MooTools框架官方页面提供了选择器性能测试页面:speed/validity selectors test for frameworks

点击右上角的"start tests"按钮,一段时间后就可以看到各个框架下各个选择器测试结果了。下表为我联系测试三次后的结果记录,可以看到,jQuery选择器的总体性能略比prototype低,比MooTools要强。但是,在我们实际些页面做交互的时候,其中选择器的差异基本上可以忽略不记(YUI在:nth-child选择器上的糟糕表现肯定要提防的)。

◆ dom操作性能

本来想从网上找一下MooTools和jQuery框架在dom操作这块的性能对比数据,结果发现,压根就没有,连个沾边的都没有。在这艰难困苦的时候,想起了伟大领袖毛主席的一句话:“自力更生,艰苦创业”。心中的小宇宙顿时爆发了,快刀乱麻,一番折腾后弄出了自己想要的测试页面。

您可以狠狠地点击这里:MooTools与jQuery一些dom操作性能对比

下面就是测试结果哈:

可以看到,除了setProperty/attr和setProperties/attrMulti方法MooTools框架性能是略微占优外,其余一些dom相关操作都完败jQuery。

小小总结:就性能这块。MooTools框架无论是选择器或是其他一些方法性能都逊于jQuery。

精彩图集

赞助商链接