不知该起什么题目,随便吧。不过我没心情逐一介绍其API,那是文档的事。比起那些随时会被废弃的方法,我更着重其内在的技术,所以我选择读源码。由于我从不用jQuery,可能理解有些偏差。不过,看了这么多类库,有许多东西都是共通。比如这个jQuery对象就是DOM对象的加工工场,把DOM对象包裹其中,外围是许多便捷的方法。我们可以想象一下太阳系,DOM就是太阳,css就其中一个行星,attr是另一个……之所以选择类数组形式,是为了用map,filter等发端于数组的同名方法进行大数量的DOM操作。好了,下面就直接写在注解中吧。
01.
var
02.
window =
this
,
03.
undefined,
04.
_jQuery = window.jQuery,
05.
_$ = window.$,
06.
//把window存入闭包中的同名变量,undefined的情形一样,的确是让更内围的作用域的方法调用时,不要跑到那么远
07.
//不过undefined在IE5之前不支持,很多类库都使用以下语句代替
08.
//window.undefined = void 0
09.
//因此这处John Resig就做得不好了
10.
//_jQuery与_$用于以后重写
11.
jQuery = window.jQuery = window.$ =
function
( selector, context ) {
12.
//用于返回一个jQuery对象
13.
return
new
jQuery.fn.init( selector, context );
14.
},
15.
//这东西看起来很唬人,其实就是想获取元素的标签名或ID
16.
quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^
#([\w-]+)$/,
17.
//检测是否一个简单的选择器,怎样才为之简单呢?
18.
//就是一重类选择器,也就是这个样子.red,如果.red .dd就不合要求了
19.
//看它的限制,一定要是类选择器,后面不能跟伪类选择器,ID选择器,属性选择器,第二重第三重的类选择器
20.
//与并联选择器
21.
isSimple = /^.[^:
#\[\.,]*$/;
01.
jQuery.fn = jQuery.prototype = {
02.
init:
function
( selector, context ) {
03.
//如果为空就把document塞进jQuery对象中
04.
selector = selector || document;
05.
//如果第一个参数是DOM对象,那它肯定有nodeType吧,
06.
//是就开始创建索引,创建类数组对象
07.
//说白了就是一个hash,只不过键是数字,值是DOM对象
08.
//不过它除了[0],[1]等数字键外,还有"css","attr","addClass"等字符串键,它们的值对应方法
09.
//length属性是就Array.prototype.slice与map,filter等方法准备
10.
//this.context是作为下次搜索的起点,如DOMElement.getElementsByTagName("span")
11.
if
( selector.nodeType ) {
12.
this
[0] = selector;
13.
this
.length = 1;
14.
this
.context = selector;
15.
return
this
;
16.
}
17.
//如果传入的是CSS selector字段
18.
if
(
typeof
selector ===
"string"
) {
19.
//如果是很单的tagName或ID
20.
var
match = quickExpr.exec( selector );
21.
//选择器类似h1的情形
22.
if
( match && (match[1] || !context) ) {
23.
//如果是标签
24.
if
( match[1] )
25.
//clean方法不厚道地放到800行之后,针对许多特殊情况做处理
26.
selector = jQuery.clean( [ match[1] ], context );
27.
// HANDLE: $("#id")
28.
else
{
29.
var
elem = document.getElementById( match[3] );
30.
// Handle the case where IE and Opera return items
31.
// by name instead of ID
32.
//在IE与Opera中,ID并不一定返回一个元素,这时用name来查找
33.
if
( elem && elem.id != match[3] )
34.
return
jQuery().find( selector );
35.
//由于ID有排他性,因此需要清空前面的context,
36.
var
ret = jQuery( elem || [] );
37.
//重设搜索起点,
38.
ret.context = document;
39.
//安装DOM对象
40.
ret.selector = selector;
41.
return
ret;
42.
}
43.
// HANDLE: $(expr, [context])
44.
// (which is just equivalent to: $(content).find(expr)
45.
}
else
46.
//处理非常复杂的选择器,如镶嵌的CSS3选择器
47.
return
jQuery( context ).find( selector );
48.
// HANDLE: $(function)
49.
// Shortcut for document ready
50.
//著名的DOMReady的,就是美元符号里面传入一个匿名函数
51.
}
else
if
( jQuery.isFunction( selector ) )
52.
return
jQuery( document ).ready( selector );
53.
// Make sure that old selector state is passed along
54.
if
( selector.selector && selector.context ) {
55.
this
.selector = selector.selector;
56.
this
.context = selector.context;
57.
}
58.
//确保以jQuery的类数组对象返回
59.
return
this
.setArray(jQuery.isArray( selector ) ?
60.
selector :
61.
jQuery.makeArray(selector));
62.
},
基本上init就是个大熔炉,根据传入参数的类型做出不同的处理,如DOM对象,字符串,数组对象与NodeList这样的类数组对象转换成jQuery对象,如果是函数,则改成DOM加载。
01.
// Start with an empty selector
02.
selector:
""
,
03.
// The current version of jQuery being used
04.
jquery:
"1.3.2"
,
05.
//返回jQuery对象所包裹的DOM对象的数量
06.
size:
function
() {
07.
return
this
.length;
08.
},
09.
//jQuery里面的方法都有一个特点,就是功能多
10.
//如著名的css,即是读方法也是写方法
11.
//这个可以返回一个纯数组
12.
//也可以返回一个纯净的DOM对象(根据索引值)
13.
get:
function
( num ) {
14.
return
num === undefined ?
15.
// Return a 'clean' array
16.
Array.prototype.slice.call(
this
) :
17.
// Return just the object
18.
this
[ num ];
19.
},
01.
// Take an array of elements and push it onto the stack
02.
// (returning the new matched element set)
03.
pushStack:
function
( elems, name, selector ) {
04.
//创建一个新的jQuery对象
05.
var
ret = jQuery( elems );
06.
//保存原来jQuery对象的引用
07.
ret.prevObject =
this
;
08.
//把原来的context移过来,context在jQuery通常用作搜索的新起点
09.
ret.context =
this
.context;
10.
//把selector标记为一个特殊的字符串,以后再解析为jQuery对象
11.
if
( name ===
"find"
)
12.
ret.selector =
this
.selector + (
this
.selector ?
" "
:
""
) + selector;
13.
else
if
( name )
14.
ret.selector =
this
.selector +
"."
+ name +
"("
+ selector +
")"
;
15.
// Return the newly-formed element set
16.
return
ret;
17.
},
18.
19.
// Force the current matched set of elements to become
20.
// the specified array of elements (destroying the stack in the process)
21.
// You should use pushStack() in order to do this, but maintain the stack
22.
//把许多元素一并放置到新的jQuery对象中,由于用Array.prototype.push,不用自己维护长度
23.
setArray:
function
( elems ) {
24.
// Resetting the length to 0, then using the native Array push
25.
// is a super-fast way to populate an object with array-like properties
26.
this
.length = 0;
27.
Array.prototype.push.apply(
this
, elems );
28.
29.
return
this
;
30.
},
31.
32.
// Execute a callback for every element in the matched set.
33.
// (You can seed the arguments with an array of args, but this is
34.
// only used internally.)
35.
//类似javascript1.6的forEach迭代器
36.
//这里是原型方法调用静态方法
37.
each:
function
( callback, args ) {
38.
return
jQuery.each(
this
, callback, args );
39.
},
40.
41.
//返回(DOM对象)elem在jQuery对象的位置(仅指数字键)
42.
//inArray的参数可以是jQuery对象,也可以是DOM对象
43.
//有点类似数组的indexOf
44.
index:
function
( elem ) {
45.
// Locate the position of the desired element
46.
return
jQuery.inArray(
47.
// If it receives a jQuery object, the first element is used
48.
elem && elem.jquery ? elem[0] : elem
49.
,
this
);
50.
},
51.
//这是个异常复杂的方法
52.
//根据参数判断是读方法还是写方法
53.
attr:
function
( name, value, type ) {
54.
var
options = name;
55.
56.
// Look for the case where we're accessing a style value
57.
if
(
typeof
name ===
"string"
)
58.
if
( value === undefined )
59.
//读方法,获取相应属性
60.
return
this
[0] && jQuery[ type ||
"attr"
](
this
[0], name );
61.
62.
else
{
63.
//写方法,设置相应属性
64.
//一个代理对象
65.
options = {};
66.
options[ name ] = value;
67.
}
68.
69.
// Check to see if we're setting style values
70.
//真正是用其静态方法工作,静态方法的优先级是相当高的,排列如下:
71.
//foo.abc() 高于 this.abc()
72.
//构造函数内的 this.abc() 高于 原型方法foo.prototype.abc
73.
//极晚绑定 fooInstance.abc()是优先级最低
74.
return
this
.each(
function
(i){
75.
// Set all the styles
76.
for
( name
in
options )
77.
jQuery.attr(
78.
type ?
79.
this
.style :
80.
this
,
81.
name, jQuery.prop(
this
, options[ name ], type, i, name )
82.
);
83.
});
84.
},