jQuery與MooTools庫的一些比對
我上大學那會兒從事的項目用的是jQuery,畢業后工作所從事的項目用的是MooTools。很幸運短期內有機會接觸兩款不同設計風格的優秀的JavaScript庫。今天就我自己的一些認識比對下這兩個JS框架,更多的是希望大家能夠對MooTools這個JS框架有更多的認識。畢竟,大多數從事web前端的人對上手容易的jQuery更熟悉些。
51CTO推薦專題:jQuery從入門到精通
一、API設計
就API的設計上來講,無論是MooTools,或是其他類似YUI的JS框架都比jQuery略遜一籌。
API是什么?根據某些著作的回答,API是對所需知識的抽象,它將系統的復雜性隱藏起來。例如汽車的方向盤,電視機上的按鈕。一個API設計的好壞可以從下面幾個方面評估:可理解性、一致性、預見性、簡單性、保護性。
◆ 可理解性
例如selector(選擇器)。隨便舉個選擇器的例子(jQuery):
- $("#jQuery div")
選擇器的寫法是與CSS的選擇器是一脈相承的。因此對于很多寫頁面的人來講,可以很輕松地使用jQuery找到自己想要的那根蔥。jQuery后來的版本之所以把XPath干掉,或許就是因為理解性上的問題吧。當然,MooTools也是支持CSS選擇器的,只不過,其不是使用一個美元符號$,而是兩個$$,貌似是學習prototype框架,返回的是數組。
- $$("#MooTools div")
如果MooTools只走到這一步,我覺得還好,貌似跟jQuery的可理解性打個小平手。只可惜,MooTools還有一個單個美元符號$的選擇器,其中參數只能是元素的id,例如:
- $("MooTools")
這玩意,選擇的貌似是有個MooTools元素擴展方法的對象。如果不存在,應用元素方法的時候(eg: addClass)則會報錯。
也就是說MooTools選擇元素,根據用法的不同,有時候返回的可能就是數組,有時候又是元素對象。這難免讓對JS熟悉,對CSS較熟悉的人員有了理解和使用上的困難了。不過這不能怪MooTools,設計架構上的不同導致MooTools有時候需要返回元素對象,而不是元素對象數組。
因此,從理解性上來說,MooTools遜于jQuery了。
◆ 一致性
JS框架的一致性的主要體現之一就是鏈式調用,例如(jQuery):
- $("#jQuery").css("color", "red").height(200);
MooTools也是支持鏈式調用的,例如(MooTools):
- $$("#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的做法是:
- $.trim(myString);
MooTools做法是:
- myString.trim();
乍一看,似乎MooTools框架的做法更符合我們的理解 → 字符串對象有個trim方法,返回過濾前后空格的字符串方法。However,隨著時間拖移,有些事情就開始發生變數了。
在ECMAScript 5(ES5)中,字符串是內置trim方法的。我們可以做個小小的測試,如下代碼:
- alert((" foo ").trim());
您可以狠狠地點擊這里:ES5 內置trim方法測試
例如,在我的FireFox 6瀏覽器下,彈出的就是foo,如下截圖:

對于一些有歷史價值的瀏覽器,就不支持,例如IE7模式下:

同樣類似的就是基于Function擴展的bind方法,MooTools中有,但是,ES5中也內置了。只是,比較幸運的是,無論是字符串trim方法,或是函數bind方法,雖然名稱沖突了,但是,所實現的功能確是一樣的,因此,也算不上沖突了。但是,萬一哪天遇到個不幸,MooTools中的某個方法與ES5中的方法同名但不同功能,然后,只能老淚縱橫了!
再舉個預見性的例子,選擇器選擇對象以及DOM對象。jQuery對jQuery對象和原生dom對象進行了分離,例如:
- $("input").bind("focus", function() {
- alert(this.value); // dom對象
- alert($(this).val()); // jQuery包裝器對象
- });
但是,在MooTools中,一些方法是在原生DOM上擴展的,MooTools元素對象和原生dom是合體的,例如:
- $$("input").addEvent("focus", function() {
- alert(this.value); // dom對象
- alert(this.get("value")); // 擴展后的dom對象
- });
“合體”的問題在于隨著瀏覽器以及一些規范的發展,原生dom可能會支持其他的一些方法,這些方法有可能就和MooTools插件中DOM擴展方法沖突。好在MooTools的方法命名屬于對稱命名,且語義明顯,這種設計可以有效避免與原生dom方法的沖突。但是,事情沒有這簡單……下面你可以看到MooTools中DOM元素方法的設計的一些問題(當然,不可否認,這種設計使用上相對靈活些)。
◆ 簡單性
jQuery之所以讓開發者戀戀不舍,原因之一就是其簡單。jQuery的口號就是"write less, do more."
拿dom-style的API舉例,MooTools, YUI等框架采用的是傳統對稱命名的方式(prop為property屬性縮寫):
- el.setStyle(prop, val);
- el.getStyle(prop);
- el.setStyles({ propA: valA, propB: valB });
- el.getStyles(propA, propB); // MooTools支持, 返回是個名-值對象
在jQuery里,一個CSS就把所有瓷器活都攬了:
- el.css(prop); // 表示 getStyle
- el.css(prop, val); // 表示 setStyle
- el.css({ propA: valA, propB: valB }); // 表示 setStyles
- el.css(prop, func); // func 是一個返回 val 值的函數
雖然參數類似,但是jQuery只要記一個名字,而MooTools卻要N個,且名字也比較長(必須完整且長,否則易出問題)。這也是為什么jQuery更容易上手的原因。而且,jQuery更近一步,還支持func回調,且參數可以map, val可以是函數,暗藏多多surprise啊。
顯然,簡單性這塊又是jQuery好一些。
這里,我還想說點其他相關的東西。jQuery框架的短命名設計確實好,于是我就想對MooTools的元素方法進行擴展,使等同于jQuery的命名書寫方式,一是省些代碼,二是方便熟悉jQuery的新員工上手,拿還是上面dom-style的例子,MooTools如下擴展處理:
- Element.implement({
- //將mootools默認的setStyle以及setStyles方法轉化為與jQuery類似的css()形式
- css: function(key, value) {
- if ($type(key) == 'object') {
- for (var p in key) this.css(p, key[p]);
- return this;
- }
- if(!$chk(value)){
- return this.getStyle(key);
- }
- this.setStyle(key, value);
- return this;
- }
- });
于是,MooTools也支持CSS方法,例如可以直接$("mootools").css({ border: "1px solid #ddd" });。恩,看上去不錯,確實,上面的擴展在目前各個瀏覽器中是沒有任何問題的。于是,初嘗到了甜頭,我們就想模擬其他jQuery包裝器方法的擴展,例如width/height方法,如下(width舉例):
- Element.implement({
- width: function (val) {
- if ($chk(val)) {
- return this.setStyle("width", val);
- } else {
- return this.getWidth();
- }
- }
- });
看上去不錯,不是嗎?但是,人生不如意事八九,上面MooTools框架對dom進行的width方法擴展是有問題的。我們都知道,<img>元素是有width屬性的。正如上面提到的,MooTools框架的元素方法是在DOM上面直接“合體”擴展的。于是乎,對于圖片而言,使用上面擴展的width方法是會嗝屁的——原生屬性與擴展方法沖突。
- alert($("image").width()); //報錯,顯示$("image").width不是function
由此又進一步證實了jQuery在API設計上更能避免一些當下或未來潛在的沖突,更具遠見性。
◆ 保護性
jQuery有個多庫共存機制,可以有效地保護其他框架都在爭奪的$符號,有效避免了一些兼容性的問題。
- jQuery.noConflict();
- (function($) {
- $(function() {
- // 使用 $ 作為 jQuery 別名的代碼
- });
- })(jQuery);
- // 其他用 $ 作為別名的庫的代碼
而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。
#p#
三、MooTools的優勢在于?
根據上面兩項的對比,MooTools框架在API方面沒有jQuery優秀,一些DOM相關操作性能也沒有jQuery好,那我們還有什么理由選擇MooTools框架呢?MooTools框架的優勢在什么地方呢?
在講述MooTools優勢之前我想講點題外話,有位MooTools團隊成員曾說如如下讓人值得思考的話:
The MooTools team (of which I am a part) has never really focused on how popular the framework is. We are interested in writing it for our own use and for its own sake, but we don't really spend much energy trying to convince other people to use it. We don't consider ourselves adversaries to other frameworks - as I've heard it put on numerous recent occassions, we're at war with the browsers, not each other. In my own posts on the topic, my suggestion to people is to try a couple of options and choose the framework that suits your needs and your styles. You really can't make a bad choice (so please stop arguing about it!). jQuery, Prototype. YUI, Dojo, MooTools - we're all doing the same things just using different methods.
MooTools團隊(我也是其中之一)從來沒有真正關注過這個框架有 多受歡迎。我們只是對寫這個框架感興趣,為我們自己使用和它本身目的去寫,但是我們真的沒有花很多精力去讓其他人去使用這個框架。我們從不認為其它框架是 我們的競爭對手——因為我曾經在很多場合都聽說過這樣的話,我們在和瀏覽器進行斗爭,而不是相互斗爭。在我的這篇文章中,我給你們的建議是:多嘗試一些選擇,然后選擇適合你的需求和你的風格的框架。你真的不能做一個壞的選擇(因此,請停止爭吵!)。jQuery、Prototype、YUI、Dojo、 MooTools——我們都只是用不同的方法在做同樣的事。
當初我第一次聽史仲冬說MooTools庫的時候,心里有嘀咕:這玩意,基本上都沒聽過,也沒有什么人使用,應該是個稀奇古怪,糟糕的框架吧。但是,當我逐漸了解這個JS框架后,越來越喜歡之,其喜歡程度已經超過jQuery,因為它比jQuery更適合當前我所做的項目——項目大,大數據量處理以及很多復雜交互。
jQuery的因為其出色的API,使得即使不怎么懂JavaScript的人也能寫出一些自以為靠譜的代碼。再加上jQuery的重心放在了DOM上,這正好討了熱衷于頁面效果交互的一些designer和csser的歡心。如果要構建中小型動態Web站點,用jQuery沒錯。快速、簡單、優雅、漂亮。如果我是一個設計者,我也會使用它的。
但是,如果是有著成百上千頁面的大項目,有些大數據量交互與處理的項目,多人合作,多模塊化的項目,jQuery往往就顯得底氣不足,往往需要各類插件補充。要知道,jQuery插件成百上千,但大多都是狗屎。如果沒有牛人把控,項目最后也就變成了狗屎!
MooTools雖然也能用在中小項目上,但是,其潛力的發揮要在大型、需要編寫大量JavaScript的應用的網站項目上。這就是MooTools的優勢。當然,我說話都是講證據的,下面我就挑幾點說說為何大型網站項目更適合MooTools而不是jQuery。
◆ 更多的對象方法擴展
雖然說,MooTools框架直接在Array, Function對象上做方法擴展有可能會造成語后來JavaScript規范出現重復或沖突的情況,但是,不可否認的是,這些對象方法的擴展對我們的開發節約了很多的功夫。
例如字符串方法的擴展。在jQuery中,字符串相關操作的方法貌似就只有一個trim。
但是,在MooTools中,框架自帶字符串擴展方法就有14個之多,例如字符串內容檢測的contains方法,清除整個字符串中多余的空白字符串的clean方法,轉義正則表達式敏感字符的escapeRegExp方法,或是取整toInt()以及rgb顏色和16進制顏色相關轉化的字符串方法等等。在大數據量交互的時候,字符串相關處理是很多的,MooTools框架自帶的這些字符串擴展方法不可不謂帶來N多便捷。
不僅僅是字符串,MooTools對數值,函數以及數組對象都進行了擴展。尤其數組,除了其原生的方法外,MooTools還對其擴展了近20個方法。這使得偶們在處理數組的時候基本上所向披靡了。總之,MooTools框架在各類JavaScript類型對象上做了新方法的擴展,以便我們可以更輕松更簡單地應付各類復雜應用和眾多數據處理。這顯然與jQuery重在DOM的設計理念不同了。
◆ 數據處理利器之Hash概念
Hash,俗稱哈希,是jQuery中沒有而MooTools中有且很贊的一個玩意。Hash是一個重新實現的Object({}), 被專門用于數據的存取,和原來的Object({})的區別是: 它不會在進行存值,取值或迭代的時候處理對象的prototype中的內容。在MooTools中,Hash對象和Array對象(json基本構成啦)聯合使用,不是我吹,再TM龐雜的數據,都能輕松應付。這讓我想起了我們小秘書餐廳詳細頁的選菜交互,如果沒有Hash這個玩意,我可真不知道該如何下手;或句話說,如果不是使用的MooTools作為框架,而是jQuery;這里的復雜的交互實現估計就是一場夢了。
◆ 面向對象的設計思想
MooTools是一款面向對象的設計思想框架。講求繼承,模塊化與重用性。雖然說其new Class({})的構造有些讓人不好理解,使用也頗有些既定規則,但是,實際上,這玩意要是能“挺過去”,還真的很有用的。舉個關于半透明遮罩層的例子吧。我們構建一個名叫Overlay的類,然后其相關的代碼就如下:
- var Overlay = new Class({
- Implements: [Options, Events],
- getOptions: function() {
- return {
- name:'',
- duration: 200,
- colour: '#000',
- opacity: 0.35,
- zIndex: 99,
- container: document.body,
- onClick: $empty
- };
- },
- initialize: function(options) {
- //......
- return this.position();
- },
- position: function() {
- //......
- },
- show: function() {
- //......
- },
- hide: function(dispose) {
- //......
- },
- dispose: function() {
- //......
- }
- });
于是,當我們需要半透明遮罩層的時候,直接:
- var myOverlay = new Overlay();
Overlay類中的position, hide, show等方法都是外部可見的。我們可是使用類似:
- myOverlay.hide()
讓遮罩層隱藏。當然,我們可以再定義一個新的類,這個類繼承或使用Overlay類,例如我們很常用的彈框效果咯,等等。雖然,MooTools這種強制面向對象風格的設計有些淡化了JavaScript語言本身的一些優美特性。但是,當項目龐大,JavaScript代碼量巨大的時候,這種面向對象的設計理念還是相當受用的。項目越大,偶們所節省的代碼量就越多。
◆ Cookie的讀寫
MooTools框架自帶Cookie讀寫的方法,支持指定域和路徑。而jQuery框架中要想實現Cookie的讀寫,需要借助于專門的cookie插件,額外的插件,顯然jQuery就折騰了。HTML5 localStorage本地存儲實際應用這篇文章的IE瀏覽器Cookie的讀寫就是使用MooTools框架自帶的Cookie方法。很簡單,很好使用。
◆ swf文件的載人
MooTools框架自帶Swiff類,可以實現頁面上flash文件的載入,而不需要求助google的swfobject方法。
上面這個鐘表flash的效果代碼如下:
- var obj = new Swiff('http://www.zhangxinxu.com/study/flash/as3_clock_2.swf', {
- width: 300,
- height: 300,
- container: $("swfBox"),
- params: {
- wmode: 'opaque',
- bgcolor: '#eeeeee'
- }
- });
◆ 更全面的動畫效果
MooTools框架的動畫效果實際上要比jQuery的強些,但是,不足在于其使用的API要比jQuery遜色。
說MooTools框架動畫要比jQuery強,其中之一就是MooTools動畫內置了貝塞爾運動曲線關鍵字。如:'linear', 'quad:in', 'back:in', 'bounce:out', 'elastic:out','sine:in:out'等等(下圖為Fx.Transitions方法之expo),而jQuery實現類似緩動效果,還需要借助ease插件。

◆ form表單序列化提交
MooTools自身攜帶HTML表單控件元素數據序列化方法,例如:
- $('myForm').toQueryString(); //返回 "email=bob@bob.com&zipCode=90210"
表單元素自身攜帶了ajax提交方法,如下示例:
- $('loginForm').addEvent('submit', function(e){
- e.stop(); //不提交form
- $('loginForm').send({
- onComplete: function(result) {
- $('loginPopup').set('html', result); //顯示結果
- (function(){
- $('loginPopup').hide();
- }.delay(1000)); //一秒鐘后隱藏
- }
- });
- });
而jQuery框架要實現類似的功能,還需要專門的表單序列化插件。我靠,這東一個插件,西一個插件,而且插件質量良莠不齊,搞多了會死人的。
四、最后的對比總結
首先,毋庸置疑的是jQuery和MooTools都是非常優秀的輕量級的JavaScript框架。
jQuery以其出色的API,出色的插件機制,以及在DOM方面的關注使其大受歡迎。然而,在面對大型項目的時候,其在一些功能特性上的缺失往往需要借助插件。如果團隊沒有有牛人把關的話,插件的濫用,人人都插一手的代碼會把項目代碼質量逐漸變成狗屎的。一般而言,jQuery更適合與動態的中小站點。
MooTools插件雖然在API & DOM和上手容易程度上都上不及jQuery,但是,其API以及面向對象的設計思想似乎在實際的大項目中更有價值。
因此,如果我要折騰我的個人網站,應該會使用jQuery。但是,如果是公司的大的網站項目,我會堅定不移選擇MooTools,因為更適合。
我JS水平尚淺,基本上都是些表象的對比,歡迎吐槽。
來自張鑫旭-鑫空間-鑫生活[http://www.zhangxinxu.com]
【編輯推薦】