noConflict: function( deep ) {
window.$ = _$;
if ( deep )
window.jQuery = _jQuery;
return jQuery;
}
(function(){
var
//
_jQuery = window.jQuery,
_$ = window.$,
//
})();
![]() |
![]() |
![]() |
![]() |
if ( selector.nodeType ) {
this[0] = selector;
this.length = 1;
this.context = selector;
return this;
}
点击展开
Sizzle.find = function(expr, context, isXML){
var set, match;

if ( !expr ) ...{
return [];
}

for ( var i = 0, l = Expr.order.length; i < l; i++ ) ...{
var type = Expr.order[i], match; 
if ( (match = Expr.match[ type ].exec( expr )) ) ...{
var left = RegExp.leftContext;

if ( left.substr( left.length - 1 ) !== "\\" ) ...{
match[1] = (match[1] || "").replace(/\\/g, "");
set = Expr.find[ type ]( match, context, isXML ); 
if ( set != null ) ...{
expr = expr.replace( Expr.match[ type ], "" );
break;
}
}
}
}

if ( !set ) ...{
set = context.getElementsByTagName("*");
}
return ...{set: set, expr: expr};
};
if ( left.substr( left.length - 1 ) !== "\\" ) {
match[1] = (match[1] || "").replace(/\\/g, "");
set = Expr.find[ type ]( match, context, isXML ); 
if ( set != null ) ...{
expr = expr.replace( Expr.match[ type ], "" );
break;
}
}
var Expr = Sizzle.selectors = {
//

find: ...{ 
ID: function(match, context, isXML)...{ 
if ( typeof context.getElementById !== "undefined" && !isXML ) ...{
var m = context.getElementById(match[1]);
return m ? [m] : [];
}
}, 
NAME: function(match, context, isXML)...{ 
if ( typeof context.getElementsByName !== "undefined" && !isXML ) ...{
return context.getElementsByName(match[1]);
}
}, 
TAG: function(match, context)...{
return context.getElementsByTagName(match[1]);
}
}| HTML代码 | jQuery代码 | 结果 |
| <form> <label>Name:</label> <input name="name" /> <fieldset> <label>Newsletter:</label> <input name="newsletter" /> </fieldset> </form> <input name="none" /> |
$("form input") | [ <input name="name" />, <input name="newsletter" /> ] |
首先“ancestor descendant” 作为一个表达式字符串,根据第一篇中的内容,它将执行:
// 处理 形如 $("div .container")的表达式字符串
else
return jQuery( context ).find( selector );接着查看jQuery对象的find方法:
find: function( selector ) {
// 当表达式不包含“,”符号时候 
if ( this.length === 1 && !/,/.test(selector) ) ...{
var ret = this.pushStack( [], "find", selector );
ret.length = 0;
jQuery.find( selector, this[0], ret );
return ret;
}
// 当表达式包含“,”符号时候 
else ...{ 
var elems = jQuery.map(this, function(elem)...{
return jQuery.find( selector, elem );
});
return this.pushStack( /[^+>] [^+>]/.test( selector ) ?
jQuery.unique( elems ) :
elems, "find", selector );
}
}由于jQuery.find = Sizzle; 因此查看Sizzle对象的具体实现:

点击展开
var Sizzle = function(selector, context, results, seed) {
results = results || [];
context = context || document;
if ( context.nodeType !== 1 && context.nodeType !== 9 )
return [];

if ( !selector || typeof selector !== "string" ) ...{
return results;
}
var parts = [], m, set, checkSet, check, mode, extra, prune = true;
// Reset the position of the chunker regexp (start from head)
chunker.lastIndex = 0;

while ( (m = chunker.exec(selector)) !== null ) ...{
parts.push( m[1] );

if ( m[2] ) ...{
extra = RegExp.rightContext;
break;
}
}

if ( parts.length > 1 && origPOS.exec( selector ) ) ...{ 
if ( parts.length === 2 && Expr.relative[ parts[0] ] ) ...{
set = posProcess( parts[0] + parts[1], context );
} else ...{
set = Expr.relative[ parts[0] ] ?
[ context ] :
Sizzle( parts.shift(), context );

while ( parts.length ) ...{
selector = parts.shift();
if ( Expr.relative[ selector ] )
selector += parts.shift();
set = posProcess( selector, set );
}
}
} else ...{
var ret = seed ?
...{ expr: parts.pop(), set: makeArray(seed) } :
Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, isXML(context) );
set = Sizzle.filter( ret.expr, ret.set );

if ( parts.length > 0 ) ...{
checkSet = makeArray(set);
} else ...{
prune = false;
}

while ( parts.length ) ...{
var cur = parts.pop(), pop = cur;

if ( !Expr.relative[ cur ] ) ...{
cur = "";
} else ...{
pop = parts.pop();
}

if ( pop == null ) ...{
pop = context;
}
Expr.relative[ cur ]( checkSet, pop, isXML(context) );
}
}

if ( !checkSet ) ...{
checkSet = set;
}

if ( !checkSet ) ...{
throw "Syntax error, unrecognized expression: " + (cur || selector);
}

if ( toString.call(checkSet) === "[object Array]" ) ...{ 
if ( !prune ) ...{
results.push.apply( results, checkSet );
} else if ( context.nodeType === 1 ) ...{ 
for ( var i = 0; checkSet[i] != null; i++ ) ...{ 
if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) ...{
results.push( set[i] );
}
}
} else ...{ 
for ( var i = 0; checkSet[i] != null; i++ ) ...{ 
if ( checkSet[i] && checkSet[i].nodeType === 1 ) ...{
results.push( set[i] );
}
}
}
} else ...{
makeArray( checkSet, results );
}

if ( extra ) ...{
Sizzle( extra, context, results, seed );
}
return results;
};其中set = Sizzle.filter( ret.expr, ret.set );调用Sizzle.filter方法:

点击展开
Sizzle.filter = function(expr, set, inplace, not){
var old = expr, result = [], curLoop = set, match, anyFound;

while ( expr && set.length ) ...{ 
for ( var type in Expr.filter ) ...{ 
if ( (match = Expr.match[ type ].exec( expr )) != null ) ...{
var filter = Expr.filter[ type ], found, item;
anyFound = false;

if ( curLoop == result ) ...{
result = [];
}

if ( Expr.preFilter[ type ] ) ...{
match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not );

if ( !match ) ...{
anyFound = found = true;
} else if ( match === true ) ...{
continue;
}
}

if ( match ) ...{ 
for ( var i = 0; (item = curLoop[i]) != null; i++ ) ...{ 
if ( item ) ...{
found = filter( item, match, i, curLoop );
var pass = not ^ !!found;

if ( inplace && found != null ) ...{ 
if ( pass ) ...{
anyFound = true;
} else ...{
curLoop[i] = false;
}
} else if ( pass ) ...{//$("form input")从这里进
result.push( item );
anyFound = true;
}
}
}
}

if ( found !== undefined ) ...{ 
if ( !inplace ) ...{
curLoop = result;
}
expr = expr.replace( Expr.match[ type ], "" );

if ( !anyFound ) ...{
return [];
}
break;
}
}
}
expr = expr.replace(/\s*,\s*/, "");
// Improper expression 
if ( expr == old ) ...{ 
if ( anyFound == null ) ...{
throw "Syntax error, unrecognized expression: " + expr;
} else ...{
break;
}
}
old = expr;
}
return curLoop;
};最关键是在加粗字代码,result.push( item ); anyFound = true; 和 curLoop = result;将匹配的元素加入result中,然后赋值于curLoop。
而方法的最后返回的是curLoop。所匹配的元素就是最后所需要的jQuery对象。
2. 【parent > child】
在给定的父元素下匹配所有的子元素。
| HTML代码 | jQuery代码 | 结果 |
| <form> <label>Name:</label> <input name="name" /> <fieldset> <label>Newsletter:</label> <input name="newsletter" /> </fieldset> </form> <input name="none" /> |
$("form > input") | [ <input name="name" /> ] |
我们只要查看一下它的核心代码:

点击展开
relative: {
// 
">": function(checkSet, part, isXML)...{
// 当part为单词字符时,如$("form > input"),part为“form” 
if ( typeof part === "string" && !/\W/.test(part) ) ...{
part = isXML ? part : part.toUpperCase();

for ( var i = 0, l = checkSet.length; i < l; i++ ) ...{
var elem = checkSet[i]; 
if ( elem ) ...{
// 得到elem的父节点
var parent = elem.parentNode;
// 如果父节点名称为part值时,在checkSet[i]上赋值父节点,否则赋值false
checkSet[i] = parent.nodeName === part ? parent : false;
}
}
// 当part为非单词字符时,如$(".blue > input"),part为“.blue”
} else ...{ 
for ( var i = 0, l = checkSet.length; i < l; i++ ) ...{
var elem = checkSet[i]; 
if ( elem ) ...{
checkSet[i] = typeof part === "string" ?
elem.parentNode :
elem.parentNode === part;
}
}

if ( typeof part === "string" ) ...{
Sizzle.filter( part, checkSet, true );
}
}
},
}
从这里我们可以得到checkSet的值集合。
2. 【prev + next】
匹配所有紧接在 prev 元素后的 next 元素。next (Selector) :一个有效选择器并且紧接着第一个选择器。
例子
| HTML代码 | jQuery代码 | 结果 |
| <form> <label>Name:</label> <input name="name" /> <fieldset> <label>Newsletter:</label> <input name="newsletter" /> </fieldset> </form> <input name="none" /> |
$("label + input") | [ <input name="name" />, <input name="newsletter" /> ] |
只要查看一下它的核心代码:

点击展开
relative: {
// 
"+": function(checkSet, part)...{ 
for ( var i = 0, l = checkSet.length; i < l; i++ ) ...{
var elem = checkSet[i]; 
if ( elem ) ...{
// 得到elem的前一个节点
var cur = elem.previousSibling;
// 当cur的节点类型不为元素节点的时候,继续得到cur的前一个节点,否则循环结束 
while ( cur && cur.nodeType !== 1 ) ...{
cur = cur.previousSibling;
}
checkSet[i] = typeof part === "string" ?
cur || false :
cur === part;
}
}

if ( typeof part === "string" ) ...{
Sizzle.filter( part, checkSet, true );
}
},
//
}
从这里我们可以得到checkSet的值集合。
3. 【prev ~ next】
匹配 prev 元素之后的所有 siblings 元素。
例子
| HTML代码 | jQuery代码 | 结果 |
| <form> <label>Name:</label> <input name="name" /> <fieldset> <label>Newsletter:</label> <input name="newsletter" /> </fieldset> </form> <input name="none" /> <input name="none2" /> |
$("form ~ input") | [ <input name="none" />, <input name="none2" />] |
只要查看一下它的核心代码:
relative: {
// 
"~": function(checkSet, part, isXML)...{
var doneName = "done" + (done++), checkFn = dirCheck;

if ( typeof part === "string" && !part.match(/\W/) ) ...{
var nodeCheck = part = isXML ? part : part.toUpperCase();
checkFn = dirNodeCheck;
}
checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
}
}
其中checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML); 调用的是dirCheck方法,它的具体实现为:

点击展开
function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { 
for ( var i = 0, l = checkSet.length; i < l; i++ ) ...{
var elem = checkSet[i]; 
if ( elem ) ...{
elem = elem[dir];
var match = false;

while ( elem && elem.nodeType ) ...{ 
if ( elem[doneName] ) ...{
match = checkSet[ elem[doneName] ];
break;
}

if ( elem.nodeType === 1 ) ...{
if ( !isXML )
elem[doneName] = i;

if ( typeof cur !== "string" ) ...{ 
if ( elem === cur ) ...{
match = true;
break;
}
} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) ...{
match = elem;
break;
}
}
// 由于这里dir为previousSibling,所以这里利用循环不断得到elem的前一个节点,并且赋值checkSet数组
elem = elem[dir];
}
checkSet[i] = match;
}
}
}从这里我们可以得到checkSet的值集合。
三、简单
1. 【:first】,【:last】,【:even】,【:odd】,【 :eq(index) 】,【 :gt(index) 】,【 :lt(index) 】和 【 :not(selector) 】
:first 匹配找到的第一个元素。
:last 匹配找到的最后一个元素。
:even 匹配所有索引值为偶数的元素,从 0 开始计数。
:odd 匹配所有索引值为奇数的元素,从 0 开始计数。
:eq(index) 匹配一个给定索引值的元素。
:gt(index) 匹配所有大于给定索引值的元素。
:lt(index) 匹配所有小于给定索引值的元素。
:not(selector) 去除所有与给定选择器匹配的元素。
例子
| HTML代码 | jQuery代码 |
| <table> <tr><td>Header 1</td></tr> <tr><td>Value 1</td></tr> <tr><td>Value 2</td></tr> </table> |
$("tr:first"),$("tr:last"),$("tr:even"),$("tr:odd"),$("tr:eq(1)"),$("tr:gt(0)") |
首先我们看下它的一个正则表达式:
POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,核心代码从Sizzle.filter开始:
接着看下Expr.setFilters的具体实现:

点击展开
setFilters: { 
first: function(elem, i)...{
return i === 0;
}, 
last: function(elem, i, match, array)...{
return i === array.length - 1;
}, 
even: function(elem, i)...{
return i % 2 === 0;
}, 
odd: function(elem, i)...{
return i % 2 === 1;
}, 
lt: function(elem, i, match)...{
return i < match[3] - 0;
}, 
gt: function(elem, i, match)...{
return i > match[3] - 0;
}, 
nth: function(elem, i, match)...{
return match[3] - 0 == i;
}, 
eq: function(elem, i, match)...{
return match[3] - 0 == i;
}
}噢,所有的标识 主要在这里判断elem元素在集合中的逻辑位置,并且返回一个布尔值。
接着 match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not ); Expr.prefilter的具体实现,主要核心代码为:

点击展开
PSEUDO: function(match, curLoop, inplace, result, not){ 
if ( match[1] === "not" ) ...{
// 代码1 
if ( match[3].match(chunker).length > 1 ) ...{
match[3] = Sizzle(match[3], null, null, curLoop);
} else ...{
var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); 
if ( !inplace ) ...{
result.push.apply( result, ret );
}
return false;
}
} else if ( Expr.match.POS.test( match[0] ) ) ...{
return true;
}
return match;
}
当match[1]匹配中包含为“not”时,即表达式字符串中包含:not时,发生“代码1”;否则,根据POS的正则表达式判断返回true。
最后将匹配的item元素入栈,即 result.push( item )。Sizzle.filter最后返回的是curLoop。所匹配的元素就是最后所需要的jQuery对象。
这篇主要讲述 基础,层级,简单的原理,下一篇将讲述选择器剩下的框题 内容,可见性,属性,子元素,表单,表单对象属性等等原理