读一个开源框架,大家最想学到的就是设计的思想和实现的技巧。最近读jQuery源码,记下我对大师作品的理解和心得,跟大家分享,权当抛砖引玉。
先附上jQuery的代码结构。
(function(){ //jQuery变量定义 var jQuery = function(){...}; //jQuery原型定义(包含核心方法) jQuery.fn = jQuery.prototype = {...}; //看上去很奇怪吧? 非常巧妙的设计,后面详细介绍 jQuery.fn.init.prototype = jQuery.fn; //提供jQuery静态方法与对象方法的扩展函数 jQuery.extend = jQuery.fn.extend = function(){...}; //后面依次有多个对jQuery静态方法的扩展 jQuery.extend({...}); //后面依次有多个对jQuery对象方法的扩展 jQuery.fn.extend({...}); jQuery.support = (function() {...})(); //提供统一时间管理,jQuery内部使用,并不对外开放 jQuery.event = {...}; //Event类似于Java的POJO类.传递事件的对象 jQuery.Event = function( src, props ) {...}; //Sizzle选择器,一个框架,可独立使用。 (function(){ ... jQuery.find = Sizzle; ... })(); ... //将定义的jQuery定义为全局变量 window.jQuery = window.$ = jQuery; ... })();
在结构上非常的清晰,定义一个jQuery对象,对jQuery对象进行扩展,赋给window,变成全局变量。就以下几点做介绍:
1). 自执行的匿名函数。
2). $("...")形式调用返回 jQuery.fn.init对象。
3). 框架里最常见的 extend 函数。
一. 自执行匿名函数。
对javascript有一定基础的都应该知道自执行匿名函数的好处。js是函数作用域。在函数里定义的变量都是局部变量,这样就很好的避免了过多的全局变量(jQuery仅仅2个全局变量jQuery和$)。由于闭包属性,虽然函数自执行结束了,但自执行函数里面定义的局部函数和变量还是能够被定义成全局变量的jQuery和$所引用到,类似于Java的私有变量。好处可见一斑。
二. $("...")形式调用返回 jQuery.fn.init对象。
这是我刚看源码的时候最不理解的地方。
var jQuery = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' return new jQuery.fn.init( selector, context, rootjQuery ); } 和 jQuery.fn.init.prototype = jQuery.fn;
var jQuery = function( selector, context ) { return new jQuery( selector, context); }兄弟,你确定这样? 明眼人一看就知道严重的问题所在,死递归!
var jQuery = function( selector, context ) { return new A( selector, context); } var A = function(){ if(this.init) { this.init(); } }; A.prototype = jQuery.prototype;这样就解决了上面的问题,因为jQuery和A拥有同一个原型,所以生成的对象都拥有相同的方法。但是还是感觉A定义的有些多余,是不是?
var jQuery = function( selector, context ) { //如果以$("#id") 方式调用this就不是jQuery.这样返回jQuery对象 if(!(this instanceof jQuery)) { return new jQuery(selector, context); } if(this.init) { this.init(); } } //这行就可以注释了 //jQuery.fn.init.prototype = jQuery.fn;