// Reset the position of the chunker regexp (start from head) // 分割快表达式,对于碰到并联表达式,则暂时结束,将余下的并联表达式保存在extra中 // 如#info .p,div.red > a do { chunker.exec( "" ); m = chunker.exec( soFar );
if ( m ) { soFar = m[3];
parts.push( m[1] ); //根据上面的chunker正则,如果存在并联表达式,那么exec之后,m[2]的值为 "," if ( m[2] ) { //m[3]为剩余的并联表达式 extra = m[3]; break; } } } while ( m ); //会被切割为如下: //parts ["#info",".p"] ,extra : div.red > a //判断是否存在位置伪类 origPOS,如 :frist,:last 等,如果存在位置伪类,则采取自左向右搜索 if ( parts.length > 1 && origPOS.exec( selector ) ) {
if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { set = posProcess( parts[0] + parts[1], context, seed );
} else { // Take a shortcut and set the context if the root selector is an ID // (but not if it'll be faster if the inner selector is an ID) // 这里主要修改context,如果表达式的开头为ID类型,且最后一个表达式非ID类型 // 所有的查询,使用到sizzle.selector.find的,只有最后一个节点,其它的节点都可以采用关系来决定 // 之所以只有第一个为id的时候可以修改context,且最后一个不能为ID,因为getElementById只在document中存在 // 在element中不存在该方法,如最后一个元素为ID,那么直接就会报错 // 那么将context修改为ID所在节点,用来提高效率 // 如:$("#info .p"); 那么自动修改为如下: $(".p",$("#info")); if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { //调用find方法,查询parts中的第一个元素,返回临时结果 //如以上的#info .p 那么会直接查询#info ,返回结果 ret = Sizzle.find( parts.shift(), context, contextXML ); //然后修改context context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; }