这是每一个框架都遇到的问题,是使用原型扩展实现链式调用,还是把方法都绑定都一个对象中。如果使用原型扩展就意味着与其他所有走这条路的框架为敌,在这条路上有两个令人望而生畏的对手——Prototype与mootools。如果把方法都绑定都一个对象中(我通常称之为命名空间对象),方法调用起来就不那么优雅,即使是jQuery,也只能让实现节点的链式操作。但一个框架所能达到的高度,是由它的基础设施决定。jQuery在它所涉及的方面算是做得尽善尽美了,但有没有想到,mootools实现与此相同的功能,所需的代码少多了。这是因为jQuery就一个jQuery对象在干活,而 mootools那边却都是武装到牙齿的Array,String,Number,Class,Event,Element等一大堆对象。原型扩展的好处显然易见,我们直接就可以在字面量上实现链式操作。如果是第二种,想实现链式操作,就需要在一个自定义对象进行原型扩展,但这也意呋着链式操作只能在实例的方法中进行,需要new一下。John Resigs想歪脑,搞了个无new实例化,减轻这种调用的痛苦(可能对其他语言的人来说,一大堆分开的方法调用不算什么,但在JS界,已经大规模使用链式操作,而你写JS时还是一个个方法地调用,明显是不合潮流,会“被落后”!)
// jQuery$.trim(" abc ");// Google Closure Librarygoog.string.trim(" abc "); // Dojo Toolkitdojo.string.trim(" abc ");
像jquery这样分层结构不明显的库,会把这些工具方法都依附到命名空间对象上,但如果库的规模很大,像Google Closure那样就不行,会很乱很乱,调用方法时内部有一个方法寻找的过程,这里会出现性能耗消。由于直接是返回没有什么扩展的原生对象,第二次调用就可能“链”不起来了。
//假设我已为jQuery添加了capitalize方法$.capitalize($.trim(" abc "));
是不是很丑鄙呢?!但现在我想通了,我的框架现在还很弱小,绝对不能与Prototype、mootools为敌,要不就会被它们扼杀于襁褓之中。我想了好久,把原生对象的(原型)方法划分为三个层次。第一种是所有浏览器都支持的,第二种是IE6不支持,但已列入ECMA草案的,如 javascript1.6的迭代器,它们不使用新的语言特征就能模拟出来的,第三种是自定义方法,话需如此,有些方法,许多主流框架都实现了的,如 string的capitalize、camelize、substitute,array的unique、flatten,object的each或 forEach。第一种我们不用管,第二种只是个兼容的问题,实现方法大同小异,反正效果出来是一样就行了。第三种如果也加入到原型中,很容易与其他类库造成命名冲突,因为它们有时仅仅是名字一样,要达到的目的完全是两码事。嗯,又是时候隆重推介我全新的链式操作。
我们知道,query之所以能链式调用,它的方法每次都返回拥有所有方法的对象。这种对象,我们称之为实例,因为它可以廉价地调用其原型链上的方法。我们反过来想,原型链其实也是一个个对象。我们可以独立地实现这些对象,我称之为扩展方法集合体,如stringExt、numberExt、arrayExt。剩下的是“实例”问题,“实例”能拥有所有方法,包括原生的以及自定义的。很明显,让一个对象干四种原生对象的活是不现实的,我相应地搞了四种对象。这些对象,我称之为代理对象,都是方法集体合,但这些方法与扩展方法集合体的截然不同,它们都是代理方法,里面的逻辑一模一样,不同的是函数体上附了一个方法名,如 “toArray”、"camelize"啦。最开始的时候,我们把这个操作对象放进一个入口函数(chain)。这其实是一个适配器,但为了简单起见,我暂时略去这些逻辑,在里面直接调用链式函数(adjustProxy)就算。此函数会根据操作对象的类型,选择不同的代理对象,或者干脆不做,直接返回。最着就等这个代理对象的某个方法被调用了,我说过它只是代理方法,唯一不同的是方法名与所在对象。被调用时,它会先从自己身上得到方法名与从内部的this那里得到操作对象target与其类型。就算这类型其实也可以通过计算得到,但既然上次已计算过,就不谓重复而已。有了方法名,我们就判定操作对象是否天生支持此方法,没有则从相应扩展方法集合体寻找相应同名方法。然后是调用方法,把得到的结果再放进链式函数(adjustProxy)中……这样就实现链式操作了。
分享两个高手写的
$(document).ready(function(){ //这个就是传说的ready
$(".stripe tr").mouseover(function(){
//如果鼠标移到class为stripe的表格的tr上时,执行函数
$(this).addClass("over");}).mouseout(function(){
//给这行添加class值为over,并且当鼠标一出该行时执行函数
$(this).removeClass("over");}) //移除该行的class
$(".stripe tr:even").addClass("alt");
//给class为stripe的表格的偶数行添加class值为alt
});
$(function(){
$(".has_children").click(function(){
$(this).addClass("highlight")
.children("a")
.show().end()
.siblings()
.removeClass("highlight")
.children("a")
.hide();
});
});
var tdObj = $(this);
var text = tdObj.html();
tdObj.html("");
var inputObj = $("<input type='text' />").css("border-width","0")
.css("font-size","16px").width(tdObj.width())
.css("background-color",tdObj.css("background-color"))
.val(text).appendTo(tdObj);
本文转自My_King1 51CTO博客,原文链接:http://blog.51cto.com/apprentice/1360779,如需转载请自行联系原作者