Skip to content

Commit 17fba37

Browse files
author
swaydeng
committed
分析完几个基础的、核心的方法
1 parent 2fd4cc5 commit 17fba37

2 files changed

Lines changed: 101 additions & 38 deletions

File tree

demo/traversing/traversing.html

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<!DOCTYPE html>
2+
<html lang="zh-CN">
3+
<head>
4+
<meta charset="gbk"/>
5+
<title>°¢Àï°Í°Í</title>
6+
<meta name="description" content=""/>
7+
<meta name="keywords" content=""/>
8+
<script type="text/javascript" src="../../src/jquery-1.8.3.js"></script>
9+
<base target="_blank"/>
10+
</head>
11+
<body>
12+
13+
<ul>
14+
<li>Hello 1</li>
15+
<li>Hello 2</li>
16+
<li class="test">Hello 3</li>
17+
<li class="aa">Hello 4</li>
18+
<li>Hello 5</li>
19+
<li class="aa">Hello 6</li>
20+
<li class="aa">Hello 7</li>
21+
<li class="util-here">Hello 8</li>
22+
<li class="aa">Hello 9</li>
23+
</ul>
24+
25+
<script>
26+
(function ($) {
27+
28+
var n = $('ul li');
29+
var resultA = $.filter('.aa', n);
30+
var resultB = $.filter('.aa', n, true);
31+
console.log(resultA.length + ',' + resultA.selector);
32+
console.log(resultB.length + ',' + resultB.selector);
33+
34+
})(jQuery);
35+
</script>
36+
</body>
37+
</html>

traversing.js

Lines changed: 64 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ jQuery.each({
181181
parents: function( elem ) {
182182
return jQuery.dir( elem, "parentNode" );
183183
},
184-
parentsUntil: function( elem, i, until ) { // i应当是后续调用map时传入的index,但是目前并没有用
184+
parentsUntil: function( elem, i, until ) { // i 是做什么的呢?
185185
return jQuery.dir( elem, "parentNode", until );
186186
},
187187
next: function( elem ) {
@@ -215,45 +215,65 @@ jQuery.each({
215215
}
216216
}, function( name, fn ) {
217217
jQuery.fn[ name ] = function( until, selector ) {
218-
var ret = jQuery.map( this, fn, until );
218+
/* this 是调用该 name 方法的 jQuery 对象,
219+
* $.map 的官方文档里指明接受两个参数,但这里我们看到其实传了三个参数
220+
* 其实第三个参数会以回调函数 fn 的第三个参数的形式传入,其实就是这样:
221+
* $.map(arrayOrObject, function (value, indexOrKey, until) { ... }, until)
222+
* value是一个HTML原生节点元素, until只有三个以Until结尾的方法用得到(jQuery接口乱啊)
223+
* ret 是一个数组{Array},它包含了所有满足条件的元素
224+
*/
225+
var ret = jQuery.map( this, fn, until );
226+
227+
// 后面会根据条件过滤掉一些
219228

220-
// 若方法名不是以 Until 结尾, 则 ……
221-
// 实去除以下三个方法,他们拥有相同的参数列表:parentsUntil、 prevUntil、 nextUntil
229+
/*
230+
* 实去除以下三个方法,他们拥有相同的参数列表:
231+
* 上面通过 $.each() 批量添加的方法中,有三个方法具有相同的参数列表,这三个方法是:
232+
* parentsUntil、 prevUntil、 nextUntil,他们的参数列表形如:( elem, i, until )
233+
* 若方法名不是以 Until 结尾, 则只接受一个参数,形如:( selector )
234+
* 这时的第一个参数 until 就相当于 selector 值,所以这个判断做了一个赋值处理
235+
* Suck jQuery
236+
*/
222237
if ( !runtil.test( name ) ) {
223238
selector = until;
224239
}
225240

226-
/*
227-
* 根据API文档,只有三个以 Until 结尾的方法接受第二个参数
228-
* 并且 selector 是用来过滤(filter)用的,
229-
* 所以有下面这个if判断,且执行该逻辑
230-
*/
241+
// 如果存在合法的 selector,则从所有结果集中将满足该 selector 的元素过滤出来
231242
if ( selector && typeof selector === "string" ) {
232243
ret = jQuery.filter( selector, ret );
233244
}
234245

235-
// 参考模块开头处,guaranteedUnique[ name ] 为 true 的可能性只有name为 children、contents、next、prev时
236-
// 所以满足条件的方法名有:parent, parents, parentsUntil, nextAll, prevAll, nextUntil, prevUntil, siblings
237-
// $.unique 将DOM元素数组中重复的元素移除
246+
/* 参考模块开头处,!guaranteedUnique[ name ] 为 true 的可能性只有name为以下值时:
247+
* parent, parents, parentsUntil, nextAll, prevAll, nextUntil, prevUntil, siblings
248+
* 剩下的方法名还有:children、contents、next、prev
249+
* $.unique 将 DOM 元素数组中重复的元素移除
250+
* 总结来说,当该方法(name)需要一次处理多个元素时,结果集中可能会产生重复的,所以需要去重,否则不需要。
251+
*/
238252
ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
239253

240-
// 匹配 parents, parentsUntil, prevUntil, prevAll
241-
// 为了结果元素符合正常情况,便于使用,会对结果集进行一个倒排
254+
/* Cool thing
255+
* 匹配 parents, parentsUntil, prevUntil, prevAll
256+
* 基于本模块核心方法 dir 的移动机制,对结果进行一次倒排,便于正常理解和使用
257+
*/
242258
if ( this.length > 1 && rparentsprev.test( name ) ) {
243259
ret = ret.reverse();
244260
}
245-
261+
/* 将新元素集推到 jQuery 栈的最上面,后面的链式调用就可以直接使用了。
262+
* 并且生成一个 selector 值,这个值可以说明新元素集产生的来源。
263+
*/
246264
return this.pushStack( ret, name, core_slice.call( arguments ).join(",") );
247265
};
248266
});
249267

250268
jQuery.extend({
251269
/**
252-
* @desc
253-
* @param expr
254-
* @param elems
255-
* @param not
256-
* @return {Array}
270+
* @desc 这个方法如果不讲Sizzle的原理,单看这里的话还是很简单的,
271+
* 即:如果 not 不设置或设置为 false 时,将从 elems 中过滤出满足 expr 选择器的元素,
272+
* 相反,如果设置 not 为 true,将从 elems 中去除满足 expr 选择器的元素
273+
* @param expr 过滤选择器
274+
* @param elems 被操作的元素集
275+
* @param not {boolean} optinal
276+
* @return {Array} 满足条件的新数组
257277
*/
258278
filter: function( expr, elems, not ) {
259279
if ( not ) {
@@ -265,27 +285,27 @@ jQuery.extend({
265285
jQuery.find.matches(expr, elems);
266286
},
267287
/**
268-
* @desc 从一个元素出发(不包括出发点元素),获取迭代搜索方向上的所有元素,直到遇到document对象或遇到until匹配的元素停止
288+
* @desc 从一个元素出发(不包括出发点和结束点元素),获取迭代搜索方向上的所有元素,直到遇到document对象或遇到until匹配的元素停止
269289
* @param {Element} elem 起始元素
270-
* @param {string} dir 迭代搜索方向,可选值:'parentNode', 'nextSibling'、 'previousSibling'
271-
* @param {string} until 选择器表达式,如果遇到 until 匹配的元素,迭代终止
290+
* @param {string} dir 迭代搜索方向,可选值:(上)'parentNode', (右)'nextSibling'、 (左)'previousSibling'
291+
* @param {string} until 选择器表达式,如果遇到 until 匹配的元素,迭代终止,不包含 until 元素
272292
* @return {Array}
273293
*/
274294
dir: function( elem, dir, until ) { // 一个简单的 dir 参数,使得函数支持遍历祖先、兄长、兄弟
275295
var matched = [],
276296
cur = elem[ dir ]; // 跳过 elem 自身
277297
/**
278-
* 迭代条件(简化):cur.nodeType !== 9 && !jQuery( cur ).is( until )
279-
* 迭代访问,直到遇到document对象或遇到until匹配的元素
280-
* cur.nodeType !== 9 当前DOM节点cur不是document对象
281-
* !jQuery( cur ).is( until ) 当前DOM节点cur不匹配表达式until
282-
*
283-
* until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )
298+
* 迭代条件解释:
299+
* cur 节点存在有效,在 DOM 的世界里,元素未找到活不存在的结果都是 null,不是 undefined 。
300+
* cur.nodeType !== 9 当前元素不是 document 节点,即向上查到 document 停止。注:DOCUMENT_NODE(9)
301+
* until === undefined 边界未指定,则继续同一方向执行。
302+
* cur.nodeType !== 1 不是元素节点,则继续同一方向执行。注:ELEMENT_NODE(1)
303+
* !jQuery( cur ).is( until ) 当前元素不匹配选择器 until,即还没有到边界,则往下执行。
284304
* 这个布尔表达式也有点意思,执行最后的jQuery.is的隐含条件是:until !== undefined && cur.nodeType === 1
285305
* 复合的布尔表达式和三元表达式,能减少代码行数、稍微提升性能,但是代码晦涩,不易阅读和维护。
286306
* 也许看不懂也是jQuery风靡的原因之一
287307
*/
288-
// DOCUMENT_NODE(9)
308+
//
289309
while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
290310
if ( cur.nodeType === 1 ) {
291311
matched.push( cur );
@@ -299,6 +319,7 @@ jQuery.extend({
299319
* @param n {Element} 开始计算的元素
300320
* @param elem {Element} 跳过的元素
301321
* @return {Array} 从 n 开始直到结束的所有的兄弟元素,如果设置了elem,则不包括 elem
322+
* 思考,能用 $.dir 方法替代吗?
302323
*/
303324
sibling: function( n, elem ) {
304325
var r = [];
@@ -313,28 +334,33 @@ jQuery.extend({
313334
}
314335
});
315336

316-
// Implement the identical functionality for filter and not
317-
// 实现与 filter 和 not 同等的功能
318-
// keep 是一个布尔值
337+
/**
338+
* @desc 实现与 filter 和 not 同等的功能,目前只在 .not(selector) 和 .filter(selector) 中有调用
339+
* @param elements 被处理的元素集
340+
* @param qualifier {selector|function|element|jQueryObject}
341+
* @param keep {boolean} 满足 qualifier 条件的是否保留
342+
* @return {*}
343+
*/
319344
function winnow( elements, qualifier, keep ) {
320345

321346
// Can't pass null or undefined to indexOf in Firefox 4
322347
// Set to 0 to skip string check
323348
qualifier = qualifier || 0;
324349

325-
if ( jQuery.isFunction( qualifier ) ) {
350+
if ( jQuery.isFunction( qualifier ) ) { // function
326351
return jQuery.grep(elements, function( elem, i ) {
327352
var retVal = !!qualifier.call( elem, i, elem );
328353
return retVal === keep;
329354
});
330355

331-
} else if ( qualifier.nodeType ) {
356+
} else if ( qualifier.nodeType ) { // element
332357
return jQuery.grep(elements, function( elem, i ) {
333358
return ( elem === qualifier ) === keep;
334359
});
335360

336-
} else if ( typeof qualifier === "string" ) {
337-
var filtered = jQuery.grep(elements, function( elem ) {
361+
} else if ( typeof qualifier === "string" ) { // selector
362+
// 将所有元素节点找出来放在一个数组中
363+
var filtered = jQuery.grep(elements, function( elem ) {
338364
return elem.nodeType === 1;
339365
});
340366

@@ -344,7 +370,7 @@ function winnow( elements, qualifier, keep ) {
344370
qualifier = jQuery.filter( qualifier, filtered );
345371
}
346372
}
347-
373+
// 执行到这里只有 qualifier 是 selector , 并且不满足 isSimple 时
348374
return jQuery.grep(elements, function( elem, i ) {
349375
return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
350376
});

0 commit comments

Comments
 (0)