在jquery.fn.init()构造器函数中,通过调用jQuery(context).find(selector)函数来解析并匹配DOM元素。jQuery.find()函数实际上是引用Sizzle()函数,而Sizzle()函数仅是Sizzle引擎的构造器,它主要调用Sizzle.find()函数在DOM文档树中查找与CSS语法相匹配DOM的元素节点的集合。jQuery名字中Query的意义就体现在这里。下面我们来分析一下Sizzle构造器函数。该函数是整个Sizzle引擎的入口。
广州网站建设,网站建设,广州网页设计,广州网站设计
- var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][ ^'"]*['"]|[^[\]'"]+) +\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,
- done = 0,
- toString = Object.prototype.toString;
- /*
上边这个正则表达式比较复杂,通过逐层分解,我们可以看到它的作用
首先,可以把整个正则表达式切分为两大块
- 第一部分:((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]| [^[\]]+)+\]|\\.|[^ >+~, (\[]+)+|[>+~]]
- 第二部分: (\s*,\s*)?
- 第一部分可以以|(表示或的意思)为分界符做进一步的切分。则切分后的正则表达式如下所示
- / //正则表达式起始符
- ( //第一个子表达式
- (?:\((?:\([^()]+\) //匹配伪类选择符
- |[^()]+)+\) //匹配函数式选择符
- |\[(?:\[[^[\]]*\] //匹配属性选择符
- |['"][^'"]*['"] //匹配属性选择符
- |[^[\]'"]+)+\] //匹配属性选择符
- |\\. //匹配Class选择符
- |[^ >+~,(\[\\]+)+ //匹配关系选择符
- |[>+~] //匹配关系选择符
- )
- (\s*,\s*) //匹配选择符组中间的分隔符
- ? //非贪婪模式匹配
- / //正则表达式终止符
- g //正则表达式属性,全局匹配
- /*
- // Sizzle选择器引擎构造器函数
- //参数说明:
- // selector:选择器字符串
- // context:上下文
- // results:结果集
- // seed:种子
- var Sizzle = function(selector, context, results, seed) {
- resultsresults = results || []; //设置默认结果集为空
- contextcontext = context || document; //设置上下文为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;
- // 重置chunker 正则表达式匹配的起始位置为开始位置
- 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 && origPOS.exec( selector ) ) {
- //relative是函数对象,封装了+>~函数,表示typeof Expr.relative[ parts[0] ] ==Function
- 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);
- }
- //如果检测到选项checkSet是数组,则执行下面操作
- if ( toString.call(checkSet) === "[object Array]" ) {
- //如果checkSet没有包含set选项值
- if ( !prune ) {
- //则把checkSet推入到结果集中
- results.push.apply( results, checkSet );
- } else if ( context.nodeType === 1 ) { //如果上下文是元素类型的对象
- for ( var i = 0; checkSet[i] != null; i++ ) { //则遍历检测选项集,然后把set推入结果集中
- if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
- results.push( set[i] );
- }
- }
- } else {
- //则遍历检测选项集,然后把set推入结果集中
- 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 );
- //如果存在排序函数,则调用它对结果集进行排序
- if ( sortOrder ) {
- hasDuplicate = false; //指示已经排序
- results.sort(sortOrder); //排序结果集
- //如果没有排序,则对结果集进行重排
- if ( hasDuplicate ) {
- for ( var i = 1; i < results.length; i++ ) {
- if ( results[i] === results[i-1] ) {
- results.splice(i--, 1);
- }
- }
- }
- }
- }
- //返回匹配的结果集
- return results;
- };
广州网站建设,网站建设,广州网页设计,广州网站设计



