解构jQuery之jQuery整体架构
在前端开发过程中必然绕不开jQuery库,移动端zepto。天天用到的一个库,很久就想通读一下源码,行动力不够一直没有执行……现在终于开始学习它,参照网上大神的博文和教程辅助自己学习。自己同时也构建一个自己的jQuery库,体验造轮子的整个过程。计划就是这样子啦,下面就是行动!
jQuery源码可以精简为以下内容:
1 (function( global, factory ) { 2 3 if ( typeof module === "object" && typeof module.exports === "object" ) { 4 5 module.exports = global.document ? 6 factory( global, true ) : 7 function( w ) { 8 if ( !w.document ) { 9 throw new Error( "jQuery requires a window with a document" ); 10 } 11 return factory( w ); 12 }; 13 } else { 14 factory( global ); 15 } 16 17 }(typeof window !== "undefined" ? window : this, function( window, noGlobal ) { 18 19 var jQuery = function( selector, context ) { 20 return new jQuery.fn.init( selector, context ); 21 }; 22 23 jQuery.fn = jQuery.prototype = {}; 24 //核心方法 25 //回归调用 26 //异步队列 27 //数据缓存 28 //队列操作 29 //选择器引 30 //属性操作 31 //节点遍历 32 //文档处理 33 //样式操作 34 //属性操作 35 //事件体系 36 //ajax交互 37 //动画引擎 38 return jQuery; 39 }));
方框上面的代码是对AMD规范的支持。
jQuery整体上被包裹在一个匿名函数中,这个匿名函数再作为另一个匿名函数的参数被传入,形参factory。
"()"圆括号包裹函数声明语句,解析器会将其解析为表达式,再在后面加一对圆括号就会形成表达式调用:
(function(arg1,arg2){ //代码 }(arg1,arg2));
包裹jQuery的匿名函数相当于arg2参数,在匿名参数中被调用——factory()。
这种被称为命名空间的函数(或自执行函数、立即调用表达式函数)在开发中应该经常用到,原理可以参考我的另一篇博文:立即调用表达式。
jQuery对象的创建和调用方式
jQuery并没有使用new运算符将jQuery显式的实例化,而是直接调用其函数。如:
$().ready();
$().ajax();
源码的最后部分有这样一段代码:
window.jQuery = window.$ = jQuery;
其实我们在平时的使用中就知道,$=jQuery,$("selector") = jQuery("selector"),$()、jQuery()直接调用自身就创建了对象。这里有着非常精妙的设计。
由以上代码可以看出,jQuery()调用自身,获得的是jQuery.fn.init对象。接着看init和jQuery的关系
先执行jQuery.fn = jQuery.protorype,再执行jQuery.fn.init.prototype = jQuery.fn,合并后是:
jQuery.fn.init.prototype = jQuery.fn = jQuery.prototype;
即jQuery的prototype等于init的prototype
所以,所有挂载到jQuery.fn上的方法就是挂在到了jQuery.prototype,即挂在到了jQuery函数上,相当于挂载到了jQuery.fn.init.prototype上,即相当于挂载到了一开始的jQuery函数返回的对象上,即挂载到了我们最终使用的jQuery对象上。
参考:
慕课网jQuery源码解析 ——Aaron
jQuery源码分析系列——nuysoft