jquery 源码分析九 - Sizzle

最近一直在搞毕设,实在是没时间写博客了,零碎的时间看代码进度也不快,所以写博客一拖再拖了,今天先补一篇上来。。。

在上次写得setDocument以后,紧接着的是一些零碎的功能函数

 1 Sizzle.matches = function( expr, elements ) {
 2     return Sizzle( expr, null, null, elements );
 3 };
 4 
 5 Sizzle.matchesSelector = function( elem, expr ) {
 6     // 设置document以防万一
 7     if ( ( elem.ownerDocument || elem ) !== document ) {
 8         setDocument( elem );
 9     }
10 
11     // 确保属性值被引号包裹
12     expr = expr.replace( rattributeQuotes, "='$1']" );
13 
14     if ( support.matchesSelector && documentIsHTML &&
15         ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
16         ( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {
17 
18         try {
19             var ret = matches.call( elem, expr );
20 
21             // 在IE9下matchesSelector会返回false(在IE10+情况下,开发者模式调到IE9,8是正常的,IETester下返回false)
22             if ( ret || support.disconnectedMatch ||
23                     // 同样的,在IE9下,这种无关节点被认为是在文档片段中
24                     elem.document && elem.document.nodeType !== 11 ) {
25                 return ret;
26             }
27         } catch(e) {}
28     }
29 
30     return Sizzle( expr, document, null, [elem] ).length > 0;
31 };
32 
33 Sizzle.contains = function( context, elem ) {
34     // 设置document
35     if ( ( context.ownerDocument || context ) !== document ) {
36         setDocument( context );
37     }
38     return contains( context, elem );
39 };
40 
41 Sizzle.attr = function( elem, name ) {
42     // 设置document
43     if ( ( elem.ownerDocument || elem ) !== document ) {
44         setDocument( elem );
45     }
46 
47     var fn = Expr.attrHandle[ name.toLowerCase() ],
48         // 防止取到Object.prototype里的属性 (jQuery #13807)
49         val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
50             fn( elem, name, !documentIsHTML ) :
51             undefined;
52     
53     return val !== undefined ?
54         val :
55         support.attributes || !documentIsHTML ?
56             elem.getAttribute( name ) :
57             (val = elem.getAttributeNode(name)) && val.specified ?
58                 val.value :
59                 null;
60 };
61 
62 Sizzle.error = function( msg ) {
63     throw new Error( "Syntax error, unrecognized expression: " + msg );
64 };

在这边,Sizzle.matches和Sizzle.matchesSelector在最后都是以return Sizzle( expr, null, null, elements )形式返回的,由于在Sizzle中,在第四项有值时,就会跳过一个大的if语句块

if ( documentIsHTML && !seed ) {
}

然后会直接跳到最后执行select函数

return select( selector.replace( rtrim, "$1" ), context, results, seed );

对于select函数,先放一下。。。等看到的时候再分析。。。

接下来的是一个主要剔除重复+排序的函数,源码如下:

Sizzle.uniqueSort = function( results ) {
    var elem,
        duplicates = [],
        j = 0,
        i = 0;

    // 默认确实有重复
    hasDuplicate = !support.detectDuplicates;
    sortInput = !support.sortStable && results.slice( 0 );
    results.sort( sortOrder );

    if ( hasDuplicate ) {
        while ( (elem = results[i++]) ) {
            if ( elem === results[ i ] ) {
                j = duplicates.push( i );
            }
        }
        while ( j-- ) {
            results.splice( duplicates[ j ], 1 );
        }
    }

    // See https://github.com/jquery/sizzle/pull/225
    sortInput = null;

    return results;
};

在这里一开始先默认确实有重复项,然后在result.sort的时候,用sortOrder来排序,这个函数在setDocument中定义了,其中有一段就是设置hasDuplicate的:

if ( a === b ) {
    hasDuplicate = true;
}

注:hasDuplicate在Sizzle闭包作用域中属于全局变量。

然后是一个拿元素内文本内容的函数,主要调用了textContent,源码如下:

 1 getText = Sizzle.getText = function( elem ) {
 2     var node,
 3         ret = "",
 4         i = 0,
 5         nodeType = elem.nodeType;
 6 
 7     if ( !nodeType ) {
 8         // 如果没有nodeType,那么就认为是一个普通数组
 9         while ( (node = elem[i++]) ) {
10             ret += getText( node );
11         }
12     } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
13         // 对于元素用textContent
14         // innerText 已被移除
15         if ( typeof elem.textContent === "string" ) {
16             return elem.textContent;
17         } else {
18             // 对子节点遍历
19             for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
20                 ret += getText( elem );
21             }
22         }
23     } else if ( nodeType === 3 || nodeType === 4 ) {
24         return elem.nodeValue;
25     }
26     // 排除注释节点
27 
28     return ret;
29 };

它用了一个递归调用的方法,防止注释等节点的混入。

在后面就是一个

1 Expr = Sizzle.selectors = {
2      // .....
3 }

这里放了许多关于筛选元素的函数,暂时先跳过了。下一篇的话从后面的tokenize开始讲。明后天估计还是要去实验室搬砖,争取在零碎时间多看看源码,早点把下一篇发上来。。。

这篇好像有点短了。。。

 

posted @ 2014-04-07 21:58  胖蝎子  阅读(273)  评论(0编辑  收藏  举报