1.简介
jquery从1.3开始,使用了新的选择器–sizzle。效率超过了以前的jquery版本以及目前能见到的其他选择器。以前曾经介绍过:http://www.enjoyphp.com/archives/252 。
2.sizzle选择器与其他选择器的区别(来自http://www.cssrain.cn/article.asp?id=1315)
全文转载如下:
大家都知道 jQuery1.3.x更换了选择器引擎,选择了Sizzle。
那么Sizzle相对于jQuery以前的选择器有什么优势呢? 为什么速度能提升这么高?
最近我在国外的网站看到点内容,大概意思是这样说的。
至于Sizzle代码是怎么实现的,我也没去研究,但我可以给大家讲一个实例,也许这样大家更容易理解。
举个一个选择器来说: $(“div p”);
每个更换选择器之前,查找步骤如下:
1,先查找页面上所有的div 。
2,循环所有的div,查找每个div下的p 。
3,合并结果 。
采用Sizzle选择器之后,查找步骤如下:
1,先查找页面上所有的p 。
2,循环所有的p,查找每个p的父元素,
1)如果不是div,遍历上一层。
2)如果已经是顶层,排除此p。
3)如果是div,则保存此p元素。
3.源代码分析(摘自http://lwp8407120426.blog.163.com/blog/static/464280752009145364974/)
先看下Sizzle是怎么定义的?
var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|[^[\]]+)+\]|\\.|[^ >+~,(\[]+)+|[>+~])(\s*,\s*)?/g,
done = 0,
toString = Object.prototype.toString;
//上边的正则是不是看的眼花缭乱,我们先分析这个正则是做什么用的?
//先分成两大块
((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|[^[\]]+)+\]|\\.|[^ >+~,(\[]+)+|[>+~])
和(\s*,\s*)
后边的就不说了,很简单
前边得再进行分,在|的位置分开,|表示或
1.(?:\((?:\([^()]+\)
2.[^()]+)+\)
3.\[(?:\[[^[\]]*\]
4.[^[\]]+)+\]|\\.
5.[^ >+~,(\[]+)+ 匹配
6.[>+~] 匹配>+~ 没有子串
//(?:\([^()]+\)|[^()]+) 这段是验证:last或者是:(xxx)这样的选择器
var Sizzle = function(selector, context, results, seed) {
//确保代码不出错,上下文存在
results = results || [];
context = context || document;
//确保上下文是dom对象
if ( context.nodeType !== 1 && context.nodeType !== 9 )
return [];
//确保选择器是String
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;
}
}
//Expr和Sizzle.selector指向同一个对象,这个选择器和以前的不一样,是在没有用if else进行判断,而是用正则进行处理,具体的代码在定义Expr中。
POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,下边的代码就是判断还有没有这样的特殊函数。
if ( parts.length > 1 && Expr.match.POS.exec( selector ) ) {
//relative是函数对象,封装了+>~函数,意思就是typeof Expr.relative[ parts[0] ] ==Function
if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
var later = “”, match;
// Position selectors must be done after the filter
// 如果匹配到>+~,处理完之后(过滤上下文),选择器中的该符号去掉,再分析选择器
while ( (match = Expr.match.POS.exec( selector )) ) {
later += match[0];
selector = selector.replace( Expr.match.POS, “” );
}
set = Sizzle.filter( later, Sizzle( /\s$/.test(selector) ? selector + “*” : selector, context ) );
} else {
set = Expr.relative[ parts[0] ] ?
[ context ] :
Sizzle( parts.shift(), context );
while ( parts.length ) {
var tmpSet = [];
selector = parts.shift();
if ( Expr.relative[ selector ] )
selector += parts.shift();
for ( var i = 0, l = set.length; i < l; i++ ) {
Sizzle( selector, set[i], tmpSet );
}
set = tmpSet;
}
}
} else {
var ret = seed ?
{ expr: parts.pop(), set: makeArray(seed) } :
Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : 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;
};
4.sizzle的流程图(看不太明白,与大家共勉!)

好文章啊