码迷,mamicode.com
首页 > 其他好文 > 详细

Sizzle之tokenize

时间:2014-12-22 14:26:19      阅读:169      评论:0      收藏:0      [点我收藏+]

标签:

在Sizzle里,大体思路,当为复合选择器时,判断是否支持querySeletorAll,如果不支持则调用自写方法select。

select的功能十分冗长,下面先分析tokenize

在tokenize函数的作用是将形如‘ul.topnav > li,div‘的选择器解析为

[
    [{value:‘ul‘,type:"TAG",matches:[‘ul‘]},{value:‘.topnav‘,type:"CLASS",matches:[‘topnav‘]},{value:‘ > ‘,type:">"},{value:‘li‘,type:"TAG",matches:[‘li‘]}],
    [{value:‘div‘,type:"TAG",matches:[‘div‘]}]
]

每个逗号解析为一个数组,表示一个独立选择器项,每个独立选择器项的选择关系按照CLASS,TAG,ID和关系解析成如上格式。

这种解析的类型是下面进行查找元素的固定格式,先不考虑后面,我们先分析tokenize的实现。

//缓存函数创建函数
var createCache = function(){
    //缓存函数共用数组
    var keys = [];
    return function cache(name,value){
        // 当长度大于某常数时,清除老元素,插入新元素
        if( keys.push( name ) > 1){
            delete cache[ keys.shift() ]
        };
        return cache[name] = value;
    };
}
//缓存函数对象
//这是一个方法,通过这个方法可以将缓存数据保存在这个函数(也是对象)里。
var tokenCache = createCache();
//简易正则过滤对象
var filter = {
    TAG: /^(\w+)/,
    ID: /^#(\w+)/,
    CLASS: /^\.(\w+)/
}
//关系匹配正则
var relation = /^\s*([\>\+\~]|^\s)\s*/;
//逗号正则
var comma = /^\,/;
function tokenize(selector){
    var cached = tokenCache[selector];
    //缓存中有结果,直接返回
    if(cached){
        return cached;
    }
    // 循环条件
    var sofar = selector,
    // 结果数组
    groups = [],
    // 匹配参数
    matched,
    // 一个独立选择器项
    token = [],
    //辅助参数正则匹配结果
    match;
    //循环解析选择器
    while(sofar){
        //首次默认创建一个单独选择器项
        //之后通过判断逗号创建
        if(!matched || (match = comma.exec(sofar)) ){
            if(match){
                //保存未解析的选择器
                sofar = sofar.slice(match[0].length);
            }
            groups.push(token = []);
        }
        //每次循环设置辅助匹配参数为false,如果之后仍无匹配不存在通过break跳出循环
        matched = false;
        //匹配关系>等
        //解析保存结果
        if(match = relation.exec(sofar)){
            matched = match.shift();
            token.push({
                value: matched,
                type: match[0].replace( /\s+/g, " " )
            })
            sofar = sofar.slice(matched.length)
        }
        //匹配选择器CLASS,TAG,ID
        //解析保存结果
        for(var type in filter){
            if(match = filter[type].exec(sofar)){
                matched = match.shift();
                token.push({
                    value: matched,
                    type: type,
                    matches: match
                })
                sofar = sofar.slice(matched.length)
            }
        }
        //没有跳出循环。
        if ( !matched ) {
            break;
        }
    
    }
    //缓存结果并返回
    return (tokenCache(selector,groups));
}
console.log(tokenize(‘ul.topnav > li,div‘))
console.log(tokenize(‘a li‘))

这是我模拟输入输出结果写出的函数,jQuery源码中在实现主要功能的基础上进行了大量兼容处理。

缓存在jQuery里面非常常用,在这里重新说一遍基本思路是,将函数输入值key,和输出值保存于缓存对象中,等到下次调用函数,如果缓存对象中有值,则直接读取。

本例的缓存略微复杂,它是利用函数将缓存数据保存于同名对象中。又,作者希望几种缓存共用长度,在这里用了创建缓存函数的函数。

Sizzle之tokenize

标签:

原文地址:http://www.cnblogs.com/winderby/p/4178065.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!