1. 代码折叠是必须的。
因此必须在支持语法折叠的编辑器里打开源码。 根据折叠层次,我们可以很快知道: 所有 jQuery 的代码都在一个函数中:
(function( window, undefined ) {// jQuery 代码
})(window);
这样可以避免内部对象污染全局。传入的参数1是 window, 参数2是 undefined , 加快js搜索此二对象的速度。
2. 接着打开第一级折叠。
可以发现 jQuery 代码是按这样顺序来组织:
- 定义 jQuery 函数 ( 代码 20 - 1081 行)
- 生成 jQuery.support (代码 1083 - 1276 行)
- 和 data 有关扩展 (代码 1279 - 1510 行)
- 和队列有关扩展 (代码 1514 - 1605 行)
- 和属性有关扩展 (代码 1609 - 1988 行)
- 和事件有关扩展 (代码 1993 - 3175 行)
- 内部的Sizzle CSS Selector Engine (代码 3183 - 4518 行)
- 和节点有关扩展 (代码 4520 - 5492 行)
- 和样式有关扩展 (代码 5497 - 5825 行)
- 和ajax有关扩展 (代码 5830 - 7172 行)
- 和效果有关扩展 (代码 7176 - 7696 行)
- 和定位有关扩展 (代码 7700 - 8065 行)
下面的模块可以用上面的模块,上面的模块不需要下面的模块
3. 定义 jQuery 函数 ( 代码 20 - 1081 行)
总的代码是这样的框架:
var jQuery = (function() {// 创建 jQuery 对象
var jQuery = function( selector, context ) {
// 略
};
// 创建 jQuery.fn 对象
jQuery.fn = jQuery.prototype = {
// 略
};
// 声明 jQuery.extend
jQuery.extend = jQuery.fn.extend = function() {
// 略
};
// 使用 jQuery.extend 扩展自己
jQuery.extend({
// 略
});
// 浏览器方面的一些琐碎
// 略
// 定义全局对象
return (window.jQuery = window.$ = jQuery);
})();
从这里知道: 平时所用的 $ 其实就是 jQuery 函数的别名。
3.1 jQuery对象 (代码 23 - 26 行)
jQuery对象似乎一直都是这东西:
var jQuery = function( selector, context ) {// 实际上 jQuery 对象是 jQuery.fn.init 返回的。
return new jQuery.fn.init( selector, context, rootjQuery );
}
这个函数表示: 要想知道函数 jQuery 是什么东西,必须看 jQuery.fn.init 对象。
同时这也解释了为什么写代码不需要 new jQuery。
再看第29行 - 97行, 都是一些变量声明,这些变量在下面的函数用到。提取变量的好处: 对正则节约编译的时间, 同时能在压缩的时候获得更小的结果。
3.2 jQuery.fn 对象 (代码 99 - 320 行)
这个fn 其实是 jQuery.prototype ,这也是为啥jQuery.fn 就是扩展 jQuery对象的唯一原因。
肯能有人会疑问, jQuery 返回 new jQuery.fn.init, 也就是说,平时的函数应该是 jQuery.fn.init.prototype 所有的成员,不是 jQuery.prototype 成员。当然原因也很简单: jQuery.fn.init.prototype === jQuery.prototype (代码 322 行)
jQuery 对js对象处理和中国人讲话一样绕。这里总结下到底 jQuery 对象是个什么家伙。
jQuery 是普通函数, 返回 jQuery.fn.init 对象的实例( new jQuery.fn.init() )。
然后 jQuery.fn === jQuery.prototype === jQuery.fn.init.prototype ,最后, jQuery返回的对象的成员和 jQuery.fn 的成员匹配。
jQuery.fn 下有很多成员,下面稍作介绍:
init - 初始化(下详细说明)
constructor - 手动指定一个构造函数。 因为默认是 jQuery.fn.init
length - 让这个对象更接近一个 原生的数组
size - 返回 length
toArray - 通过 Array.prototype slice 实现生成数组
get - 即 this[ num ] ,当然作了下 参数索引 的处理。
pushStack - 加入一个元素
ready - 浏览器加载后执行(下详细说明)
end - 通过保存的 prevObject 重新返回
each - 参考 http:///xuld/archive/2011/02/13/1953907.html
jQuery.fn.position jQuery.fn.position 返回和 style.left 一样。计算方法就是先 算 offset 和父节点(offsetParent) offset, 那么就可以得到偏移。
15. 总结
分析源码的时候可以对照代码理解。jQuery虽然复杂但代码还是好读的。解读源码只要是为了更好地使用,所以知道源码后,就自然知道为什么jQuery可以做这么多事。
但jQuery始终不是唯一的框架,感叹它的设计同时,还应该看一下其它性格的框架,比如 Mootools 。