之因此把這部分放在這裏,是由於這裏用到了一些基本API,前一篇介紹事後才能使用。javascript
//jQuery經過find方法調用Sizzle引擎 //jQuery經過find方法調用Sizzle引擎 jQuery.find = Sizzle; jQuery.expr = Sizzle.selectors; jQuery.expr[":"] = jQuery.expr.pseudos; jQuery.unique = Sizzle.uniqueSort; jQuery.text = Sizzle.getText; jQuery.isXMLDoc = Sizzle.isXML; jQuery.contains = Sizzle.contains; var rneedsContext = jQuery.expr.match.needsContext; //匹配沒有其餘如class等任何屬性的標籤,就是簡單標籤, //如<input />和<div></div> var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/); //當selector爲 .header這樣的形式則爲簡單選擇符 var risSimple = /^.[^:#\[\.,]*$/; // Implement the identical functionality for filter and not //比較難啃的一個函數,傳入參數有幾種用法。後面的多個過濾函數都依賴於這個函數 //第一個參數表示element元素集,第二個參數傳入過濾函數、DOM、選擇符、數組,第三個參數爲預設結果 function winnow( elements, qualifier, not ) { if ( jQuery.isFunction( qualifier ) ) { return jQuery.grep( elements, function( elem, i ) { /* jshint -W018 */ return !!qualifier.call( elem, i, elem ) !== not; }); } if ( qualifier.nodeType ) { return jQuery.grep( elements, function( elem ) { return ( elem === qualifier ) !== not; }); } if ( typeof qualifier === "string" ) { if ( risSimple.test( qualifier ) ) { return jQuery.filter( qualifier, elements, not ); } qualifier = jQuery.filter( qualifier, elements ); } return jQuery.grep( elements, function( elem ) { return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not; }); } //過濾函數 jQuery.filter = function( expr, elems, not ) { var elem = elems[ 0 ]; if ( not ) { expr = ":not(" + expr + ")"; } //其實這兩個區別不大,都要調用Sizzle return elems.length === 1 && elem.nodeType === 1 ? jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { return elem.nodeType === 1; })); }; //開始jQuery對象的原型進行擴展 jQuery.fn.extend({ find: function( selector ) { var i, ret = [], self = this, len = self.length; //當傳入的參數是字符串類型時,調用下面的filter方法,本質是調用上面的winnow,winnow裏又視狀況調用sizzle if ( typeof selector !== "string" ) { return this.pushStack( jQuery( selector ).filter(function() { console.log('find'); console.log(self); for ( i = 0; i < len; i++ ) { //若是self包含符合selector的this,注意這裏的this是新的jQuery對象 if ( jQuery.contains( self[ i ], this ) ) { return true; } } }) ); } //不然以self[i]爲查找上下文context進行查找 for ( i = 0; i < len; i++ ) { jQuery.find( selector, self[ i ], ret ); } // Needed because $( selector, context ) becomes $( context ).find( selector ) //這裏是正常的壓棧和選擇符拼接 ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); ret.selector = this.selector ? this.selector + " " + selector : selector; return ret; }, filter: function( selector ) { return this.pushStack( winnow(this, selector || [], false) ); }, not: function( selector ) { return this.pushStack( winnow(this, selector || [], true) ); }, is: function( selector ) { //經過winnow返回的長度來判斷 return !!winnow( this, // If this is a positional/relative selector, check membership in the returned set // so $("p:first").is("p:last") won't return true for a doc with two "p". typeof selector === "string" && rneedsContext.test( selector ) ? jQuery( selector ) : selector || [], false ).length; } });