jQuery技术

JQuery Sizzle引擎源代码分析

字号+ 作者:H5之家 来源:H5之家 2016-10-05 11:00 我要评论( )

空间>博客> 转 JQuery Sizzle引擎源代码分析 Queen发表于6天前(2016-09-28 17:04:51) |评论(0)|阅读次数(17)| 0人收藏此文章, 最近在拜读艾伦在慕课网上写的JQuery课程,感觉在国内对JQuery代码分析透彻的人没几个能比得过艾伦。有没有吹牛?是不是我说

空间 >博客>

JQuery Sizzle引擎源代码分析

Queen 发表于 6天前 (2016-09-28 17:04:51)  |  评论(0)  |  阅读次数(17)| 0 人收藏此文章,     

    最近在拜读艾伦在慕课网上写的JQuery课程,感觉在国内对JQuery代码分析透彻的人没几个能比得过艾伦。有没有吹牛?是不是我说大话了?

什么是Sizzle引擎?

    我们经常使用JQuery的选择器查询元素,查询的选择器有简单也有复杂:
    简单点:“div”、“.navi”、“div.navi”。

    复杂点:"div input[type='checkbox']"、"div.navi + .section p"。

   

    Query实现查询时也是优先使用DOM标准查询函数,例如:

    document.getElementById()

    document.getElementsByTagName()

    document.getElementsByClassName()

    document.getElementsByName()

    高级浏览器还实现了:

    querySelector()

    querySelectorAll()

    由于浏览器版本差异导致的兼容问题,上面的函数并不是所有浏览器都支持。但JQuery得解决这些问题,所以就引入了Sizzle引擎。
JQuery在筛选元素时优先使用浏览器自带的高级查询函数,因为查询效率高。其次才选择使用Sizzle引擎筛选元素。

    Sizzle引擎的目的是根据传入的selector选择器筛选出元素集合。执行过程经过词法分析、编译过程。通过词法分析把一个selector字符串分解成结构化的数据以便编译过程使用。编译过程充分利用了Javascript的闭包功能,生成一个函数链,在最终匹配时再去执行这个函数链。

    举个例子,一个选择器selector的值为”Aaron input[name=ttt]”,通过词法分析,得到一个结构化数组:

[ { matches: ["div"], type: "TAG", value: "Aaron" }, { type: " ", value: " " }, { matches: ["name", "=", "ttt"], type: "ATTR", value: "[name=ttt]" } ]

    selector中的input作为一个种子集合seed。意思是Sizzle根据input查询出所有input元素,结果存放到seed集合,编译过程都是在seed集合中查询过滤。
    上面说的很粗糙,不便于理解,接下来我们就拿代码来介绍。

通过代码分析原理

    申明:下面的代码来源于Aaron在慕课网上的Jquery教程

 

    compile

/** * 编译过程 */ function compile(){ var seed = document.querySelectorAll("input"), selector = "Aaron [name=ttt]", elementMatchers = [], match = [ { matches: ["div"], type: "TAG", value: "Aaron" }, { type: " ", value: " " }, { matches: ["name", "=", "ttt"], type: "ATTR", value: "[name=ttt]" } ]; elementMatchers.push(matcherFromTokens(match)); //超级匹配器 var cached = matcherFromGroupMatchers(elementMatchers); var results = cached(seed); results[0].checked = 'checked'; }

    JQuery的compile函数包含了所有的执行过程,由于本篇介绍的重点是编译过程,所以词法分析的过程未包含,这里直接写了match结果,实际JQuery会调用tokenize()函数获取词组。
    函数中调用了两个函数:matcherFromTokens()和matcherFromGroupMatchers()。
    matcherFromTokens():返回的是一个函数,函数结构如下:

image

    返回函数格式为function(elem, context, xml),并且这个函数返回一个bool值表示elem是否匹配有效。

    matcherFromGroupMatchers():函数代码很简单,遍历seed集合,每个元素都调用elementMatcher函数。最终返回一个匹配成功的元素集合。
    由于matcherFromGroupMatchers()函数比较简单,所以就先介绍它。

   

    matcherFromGroupMatchers

function matcherFromGroupMatchers(elmentMatchers){ return function(seed){ var results = []; var matcher, elem; for(var i = 0; i < seed.length; i++){ var elem = seed[i]; matcher = elmentMatchers[0]; if(matcher(elem)){ results.push(elem); } } return results; } }

    遍历seed元素,每一个元素都调用matcher函数,返回true则添加到results数组中。

 

matcherFromTokens function matcherFromTokens(tokens){ var len = tokens.length, matcher, matchers = []; for(var i = 0; i < len; i++){ if(tokens[i].type === " "){ matchers = [addCombinator(elementMatcher(matchers))]; }else{ matcher = filter[tokens[i].type].apply(null, tokens[i].matches); matchers.push(matcher); } } return elementMatcher(matchers); }

    整个编译的核心也就在matcherFromTokens函数中,遍历分词tokens数组,分词分两大类,关系型和非关系型。关系型包括:“ ”、“>”、“+”、“~”。 剩下的都是非关系型分词。

    每一个非关系型分词都会对应一个matcher:

image

    第一个分词类型为TAG,在filter中找到matcher。第二个分词为关系分词,调用addCombinator合并之前的matcher。第三个分词类型为ATTR,在filter中找到matcher。最终matchers的值为:

image

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • JQuery动态添加和删除表格行的方法

    JQuery动态添加和删除表格行的方法

    2016-10-04 18:00

  • jqueryAPI使用之选择器

    jqueryAPI使用之选择器

    2016-09-28 15:00

  • 从零开始学习jQuery[1]

    从零开始学习jQuery[1]

    2016-09-28 14:00

  • TreeGrid 一款自己写的利用jquery实现的树形表格,可以lazy load

    TreeGrid 一款自己写的利用jquery实现的树形表格,可以lazy load

    2016-09-21 14:00

网友点评
p