jQuery1.11源碼分析(8)-----jQuery調用Sizzle引擎的相關API

之因此把這部分放在這裏,是由於這裏用到了一些基本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;
	}
});
相關文章
相關標籤/搜索