Mootools、jQuery比较,JQuery之多宗罪

看到很多人在讨论jQuery和Mootools,但是流于分析,理论,我来说说一些实际的体会吧。

首先摆明立场,我是倾向Mootools的,jQuery的很多东西让我觉得他只是名声在外,下面我会一一说明。

Prototype公布1.6的时候,我就开始在同时关注jQuery和MT。当时的MT没有jQuery出名,代码也没有jQ的精彩,但是当时他具备了一些很重要的特性,比如样式转换类的CSS,缓动类的Tween,还有很好的将两者结合的Effect类,并且在他的特效类里面,全部都和Effect类接口,使得你很容易的就创建一个活生生的widget。

MT另外一个重要的特点,是他传承了Propertyp框架的一些思想和方法,使得你能够很容易的调用MT已经封装好的类,尤其是1.2以后的Class类,可能实现上算不上精彩,但却很实用。

其实说实在的,做JS时间长的,无论那个是曾经让你多么的赏心悦目的优雅精致的一个框架,也总不自然的会咒骂两句,一些小Bug,自己动手改改也就算了,但有些很核心的东西,你怕是回天乏力,只好将就用吧!心里再把咒骂的句子重复若干遍、若干天,然后当碰到别人问,JS用啥好呢?他,他,脱口而出的还是他,然后你就会忘记自己曾经怎么样的痛苦。

还记得MT1.20Rc的时候,FormObj.toQueryString()的这个方法,没有填写值的input,他居然默认将其key也删除了。Google刚出Chrome的那时期,Mt又出状况了,当时国内一点资料都没有,我是把MT的论坛翻到底了,才找到那条解决办法。这不,到MT1.21了,Swiff类又不好使了,居然给每个new Swiff都默认设置了嵌入HTML流(就是设置Flash透明的那个属性),即使在你设置了其输出模式的条件下。好吧,小Bug总是能容忍的,不管怎么说,MT的代码思路清晰、泾渭分明,即使改,也好下手,而且改动不会很大,因为他标准化。

这时不得不列举两条jQuery的臭事,尤其是那个万恶的jQuery(),一切皆是jQuery的实例,所以都从jQuery开始(从唯物和唯心的角度讲,如果说MT是唯物的,jQ就是唯我的,唯我论其实就是一种唯心论)。有时候真的很不明白,jQuery('element')怎么就做得那么臭,尤其当我要取出一个jQuery('#elementId')的时候,竟然那么辛苦,那么龌龊,jQuery('#elementId')[0],哦my god,这是什么滴家伙?

也许有人会说,你偏心眼,对jQuery净用贬义词。也有人会说,瞧,这家伙献丑了吧?这都不懂,一切都是jQuery啊!

其实恰恰就是一切皆jQuery,才惹出了问题。首先,导致jQuery()出问题的根源在于,假如你要遍历一个数组,jQuery没有提供基于Array类的扩展,你必须jQuery([0, 1, 2, 3, 4]).each(...)。或者这么说吧,当全世界都是jQuery的时候,就会产生很多问题,就是这个jQuery实例是一个element呢?还是一个Array呢,还是一个Object呢,还是个啥啥啥啥呢?搞不清楚,搞不清楚就得拿出来问个究竟,结果就要jQuery()[0]。

在MT里面,有一系列的方法判断一个变量的引用值,究竟是exist呢,还是define呢,实在不行,干脆把它的type弄出来看看?不过我们的jQuery可是不管3721,尤其当if (!$obj)jQuery老哥会告诉你,yes it is....my god...当你尝试调用typeof 一个无情、冷漠的答案就是jQuery,yes it is....能体会我说的是什么?

这些都是jQuery中的陷阱,也许很多人会觉得用jQuery很容易上手,插件N多,要多少有多少,没有你搜不到,只有你想不到的。对于新人来说,这也无可厚非,尤其对于急于完成项目人来说。但不管项目大小,代码多少,每个过程的结束,你总会冷静沉思,我从这个过程里收获了什么?我个人以为,jQuery除了纵容一些不良习性以外,不会给你带来更多,关于JS的思考。

jQuery所谓插件其实不过浮云,jQuery源代码本身是精彩的,但你想动他一动,是不可以的。我曾经做个一些尝试,同样的sortAble,MT提供标准化的事件接口、标准化的options设置,哪怕你想修改其一些内部的东东,也没有问题,因为是标准化的,好改。jQuery就不能够了,且不说FP的代码本来就不那么好看,稍微改个什么地方,结果整个soatAble都垮了。老实话,饶是我这种动不动就写上千行JS的人,也受不了jQuery的这份折腾,真的很无语,他那拖动本身实现的就很小儿科(当然,1年多以前的光景),又碰不得,我还不只能作罢干休。

说着说着,又忍不住要说说jQuery那该死的Ajax。complete,success这些事情,都好像是Ajax这个东东凭空有的,当然,天马行空也不是不可以,但较之MT,jQuery的Ajax实现真的很小儿科。首先是有事件,Request类才具有事件的特征,事件实现了什么,事件什么时候激发。然后是Request.HTML,Request.JSON,之后是若干动态方法,和Element类的有机结合。整个流程下来,合情合理,而且你心里很明白,这样用起来也会很放心,因为出问题了,有根可循,有据可查。

我看jQuery的Ajax,一头烟雾,尤其是success和complete的参数还不是统一的,丫的像找抽一样,load方法,居然整整1年多过去了,还是那样的僵硬,死板。近期的某一个项目,我尝试利用jQuery的Ajax类封装一些高级的事件,可是我每次打开jQuery的源代码,都觉得没有什么统一的标准,可以一劳永逸的修改整个流程(这意味着,假如我修改了A和B两处,有可能A发生故障了,B需要重复的代码,或者B暂时没问题,我需要增加对B点的测试,以暴露出他是不是有问题,这是很郁闷很烦恼的)。最后我决定采取暴力封装的方法,比如有这么一段:

 

JavaScript代码
Mix.Ajax = function(option) {   
    // $(option.update)其实永远返回真   
    // 所以必须附加一条,$(option.update).length == 1,我当然不想要length > 1的jQuery实例   
    // 被传进来。   
    var update = (option.update && $(option.update) && $(option.update).length == 1) ? $(option.update) : null;   
    if (update) {   
        // 开始封装   
        // 先把用户调用complete和cancelUpdate的函数保存起来   
        var complete = option.complete, cancelUpdate = option.cancelUpdate;   
        // 伪装一个complete包   
        option.complete = function(request, status) {   
            // 终止update的条件   
            // cancelUpdate参数可能是一个函数,可能是一个变量值,   
            // 总之当cancelUpdate返回true就是中止update,就是$().load   
            if (cancelUpdate)   
                cancelUpdate = jQuery.isFunction(cancelUpdate) ? cancelUpdate.call(this, request, status, update) : cancelUpdate;   
            if (status == 'success' && !cancelUpdate) {   
                // 如果中止条件不为真   
                // 执行beforeUpdate的方法   
                if (jQuery.isFunction(option.beforeUpdate)) option.beforeUpdate.call(this, request, status, update);   
                if (!this.cancelUpdate) jQuery(update).html(request.responseText);   
                if (!this.cancelUpdate && jQuery.isFunction(option.afterUpdate)) option.afterUpdate.call(this, request, status, update);   
            }   
            // 最后才执行真正用户设定的那个complete的包   
            if (jQuery.isFunction(complete))   
                complete.call($, request, status);   
        }   
    }   
    option.async = true;   
    jQuery.ajax(option);   
}  

真的是一个丑陋的实现,不过好像只能望而兴叹吧。

还有一些很细节的地方,比如说jQuery是率先实现捕获批量对象的,但是他没有好好的发挥这个长处,比如一组批量元素setStyle,就必须要遍历这组元素。其实他是不敢,因为捕获回来的,可能是一个,可能是成群,你没法确定之后的所谓“链式操作”会不会把浏览器拖垮。又是jQuery()惹得祸。相反,由于MT很明确的区分$和$$,以及getElement和getElements的返回结果,你很清楚你所作的事情会导致什么什么结果。所以MT也不忌讳在$$('someProperty').setStyle()会对所有的捕获的元素批量设置样式。

同样的问题,蔓延在jQuery框架上下,比如bind,比如arrt。可是反观MT,由于一切都是标准,$$().addEvents(...),你可以冠冕堂皇的用而不会返回什么不必要的错误。

这一切的一切,导致到最后的结果就是,jQuery一无是处,而MT则能够真真正正的安全实现所谓“链式操作”,何况,他还不止一种链式操作的方式,通过chain可以真真正正实现上一个事件完成,下一个事件才开始。看官千万别说jQuery也有,这丫明抄的。

好了,叽叽歪歪的说三道四半天,给予那些还在彷徨做选择的人一点实际的感受,或者对于那些,真的在使用jQuery的人,请好好看清自己写的JS代码。

本文来自:青软培训(www.qingsoft.net)原文链接:http://www.qingsoft.net/bbs/html/article/1301.jhtml

你可能感兴趣的:(jquery,Ajax,chrome,mootools,FP)