Download presentation
Presentation is loading. Please wait.
Published byMartin Miller Modified 5年之前
1
By zhangpeng12@baidu.com
Sizzle引擎研究 By
2
什么是sizzle A pure-JavaScript CSS selector engine (power jQuery)
Standalone(no dependencies) Competitive performance Only 4kB with gzipped Easy to use Css3 support Bla bla ……
3
为什么需要sizzle Bugs 1. Id IE<=8不区分大小写,混淆iuput的name和id 2. class IE getAttribute ,混淆html的attribute和dom的property 非IE getElementsByClassName 3.Tag getElementsByTagName(*)混淆注释节点 性能 考虑如下选择器: div.container li:last-of-child a,div.container ul+a var mySelector = function(){ bla bla……. There gone be at least 100 lines here……. }
4
高版本浏览器(querySelector)
5
Sizzle概览 词法解析 过滤函数 种子集 结果集 编译函数匹配
6
词法解析 词法分析器又称扫描器,词法分析是指将我们编写的文本代码流解 析为一个一个的记号,分析得到的记号以供后续语法分析使用
{matches: ["div"],type: "TAG",value: "div“ }, {matches: ["aaron"], type: "CLASS", value: ".aaron"}, {match:[“”], type: " ", value: " "}, {matches: ["input"], type: "TAG", value: "input"}, {matches: ["name"], type: "ATTR", value: "[name=ttt]"} div.aaron input[name=ttt]
7
词法解析(模式) 分组(,) /^[\x20\t\r\n\f]*,[\x20\t\r\n\f]*/ 层级关系( >+~)
/^[\x20\t\r\n\f]*([>+~]|[\x20\t\r\n\f])[\x20\t\r\n\f]*/ 单个元素处理 Id Tag Class Attribute …… var characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+" var ID = new RegExp("^#(" + characterEncoding + ")") var TAG = new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ) var Class = new RegExp( "^\\.(" + characterEncoding + ")" ) …….
8
词法解析(代码) while (selector) { //分组 if (match = rcomma.exec(selector)) {
selector = selector.slice(match[0].length) groups.push((tokens = [])); } //层级关系 if ((match = rcombinators.exec(selector))) { matched = match.shift(); tokens.push({ value: matched, type: match[0].replace(rtrim, " ") }); selector = selector.slice(matched.length); //选择器 for (type in matchExpr) { if ((match = matchExpr[type].exec(selector))) { type: type, matches: match //分组 var rcomma = /^[\x20\t\r\n\f]*,[\x20\t\r\n\f]*/; //层级 var rcombinators = /^[\x20\t\r\n\f]*([>+~]|[\x20\t\r\n\f])[\x20\t\r\n\f]*/ //选择器 var TAG = /^((?:\\.|[\w*-]|[^\x00-\xa0])+)/; var matchExpr = { CLASS: /^\.((?:\\.|[\w-]|[^\x00-\xa0])+)/, TAG: /^((?:\\.|[\w*-]|[^\x00-\xa0])+)/ }
9
过滤函数 //各种类型的token的过滤器,全部返回闭包函数 Expr.filter = {
ATTR : function (name, operator, check) {return function} CHILD : function (type, what, argument, first, last) {return function} CLASS : function (className) {return function} ID : function (id) {return function} PSEUDO : function (pseudo, argument) {return function} TAG : function (nodeNameSelector) {return function} } //tag类型的过滤器,判断nodeName是否匹配,返回闭包函数 TAG: function(nodeNameSelector) { return function(elem) { return elem.nodeName && elem.nodeName.toLowerCase() === nodeNameSelector; }; }
10
结果集 div.aaron input[name=ttt] div.aaron [name=ttt] Input标签种子集合 TAG过滤
{ matches: ["div"],type: "TAG",value: "div“ }, {matches: ["aaron"], type: "CLASS", value: ".aaron"}, {match:[“”], type: " ", value: " "}, {matches: ["input"], type: "TAG", value: "input"}, {matches: ["name"], type: "ATTR", value: "[name=ttt]"} { matches: ["div"],type: "TAG",value: "div“ }, {matches: ["aaron"], type: "CLASS", value: ".aaron"}, {match:[“”], type: " ", value: " "}, {matches: ["name"], type: "ATTR", value: "[name=ttt]"} Token集简化
11
编译原理 过滤后的选择器 div.aaron [name=ttt] 过滤函数 Expr.filter = {
过滤后的token集 { matches: ["div"],type: "TAG",value: "div“ }, {matches: ["aaron"], type: "CLASS", value: ".aaron"}, {match:[“”], type: " ", value: " "}, {matches: ["name"], type: "ATTR", value: "[name=ttt]"} 过滤后的选择器 div.aaron [name=ttt] 超级匹配函数 function(){ 层次很深的闭包….. } 过滤函数 Expr.filter = { ATTR : function (name, operator, check) {return function} CHILD : function (type, what, argument, first, last) {return function} CLASS : function (className) {return function} ID : function (id) {return function} PSEUDO : function (pseudo, argument) {return function} TAG : function (nodeNameSelector) {return function} }
12
编译过程 遇到关系token(+> ~)则依次出栈合并匿名函数,其他情况压入对应的token处理函数 选择器表达式
div [name=ttt] ( )[name=ttt] [name=ttt] 超级匹配器 Function(elem){ //tag filter } Function(elem){ //attribute filter } Function(elem){ while(matcher=matchrs.pop()){ if(!matcher(elem)){ return false; } return true; Function(elem){ elem=elem[‘parentNode’]; return Function(elem){ tag filter } Function(elem){ elem=elem[‘parentNode’]; return Function(elem){ //tag filter } Matchers集合
13
超级匹配器 for item in seed if(superMatcher(item )){ resultSet.push(item);
} return resultSet
14
Thanks & Regards
Similar presentations