jQuery1.11源码分析(8)-----jQuery调用Sizzle引擎的相关API

之所以把这部分放在这里,是因为这里用到了一些基本API,前一篇介绍过后才能使用。

//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;
    }
});

jQuery1.11源码分析(8)-----jQuery调用Sizzle引擎的相关API,布布扣,bubuko.com

jQuery1.11源码分析(8)-----jQuery调用Sizzle引擎的相关API

上一篇:js操作Iframe非当前最上层窗体


下一篇:经受时延的确认(Delay ACK)