sizzle编译函数

简介:

一个人去完成一件事情,如果派多个人去做的话,只要配合默契,效率比一个人做肯定要高,效率提高,所需的时间就减少了。如果只能一个人完成,那么必须设法提高自己的劳动效率,这个提高可以是量的改变也可以是质的改变。我把这个量的改变称为空间上的改变,也就是说空间和时间是可以相互转换的。

按照解析原理与过滤器的原理一次用循环递归去匹配查找,这样的效率是很慢的,那么sizzle从给1.8开始就引入了编译的概念,就是空间换时间的算法通过缓存大量的闭包匹配器从而提高重复的效率

闭包是js的特性,我们经常会用来作为私有变量的保存处理,那么sizzle就很好的利用了这一特性,把选择器中每一个选择原子都变成了函数的处理方法,然后通过闭包保存着。在缓存在内存中去,这样有重复使用的时候就会首先调用缓存。

Sizzle对于编译这个最终的过滤器闭包是非常绕的,先通过简单的例子去展示这个一个复杂的思路。

复制代码
var filter = {
    ATTR: function(name, operator,check) {
        return function(elem) {
            var attr = elem.getAttribute(name)
            if (operator === "=") {
                if(attr === check){
                    return true
                }
            }
            return false;
        }
    },
    TAG: function(nodeNameSelector) {
        return function(elem) {
            return elem.nodeName && elem.nodeName.toLowerCase() === nodeNameSelector;
        };
    }
}

function addCombinator(matcher) {
    return function(elem, context, xml) {
        while ((elem = elem['parentNode'])) {
            if (elem.nodeType === 1) {
                //找到第一个亲密的节点,立马就用终极匹配器判断这个节点是否符合前面的规则
                return matcher(elem);
            }
        }
    }
}


function elementMatcher(matchers) {
    return matchers.length > 1 ?
    function(elem, context, xml) {
        var i = matchers.length;
        while (i--) {
            if (!matchers[i](elem, context, xml)) {
                return false;
            }
        }
        return true;
    } :
    //单个匹配器的话就返回自己即可
    matchers[0];
}



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


function compile() {
    //种子合集
    var seed = document.querySelectorAll('input')
    //选择器
    var selector = "Aaron [name=ttt]";
    var elementMatchers = [];
    var results = []
    var match = [{
        matches: ["div"],
        type: "TAG",
        value: "Aaron"
    }, {
        type: " ",
        value: " "
    }, {
        matches: ["name", "=", "ttt"],
        type: "ATTR",
        value: "[name=ttt]"
    }]
    elementMatchers.push(matcherFromTokens(match));
    var matcher, elem;
    for (var i = 0; i < seed.length; i++) {
        matcher = elementMatchers[0];
        var elem = seed[i];
        if (matcher(elem)) {
            results.push(elem);
            break;
        }
    }
    console.log(results)
}


compile();
复制代码

抛开伪类的处理,这里就是一个简化版的sizzle的流程

测试,高级浏览器


本文转自艾伦 Aaron博客园博客,原文链接:http://www.cnblogs.com/aaronjs/p/3972490.html,如需转载请自行联系原作者
相关文章
|
5月前
|
JavaScript
在循环内错误使用函数定义(js的问题)
在循环内错误使用函数定义(js的问题)
27 0
|
10天前
|
JavaScript 前端开发
JS 偏函数、函数柯里化~
该文章介绍了JavaScript中偏函数和函数柯里化的概念、实现方法和使用场景,通过代码示例展示了如何创建预设参数的函数以及如何将多参数函数转换成单参数函数的链式调用。
12 0
JS 偏函数、函数柯里化~
|
JavaScript Java
酷似js的java函数简写——lambda表达式
酷似js的java函数简写——lambda表达式
|
JavaScript
js中递归调用返回值为undefined问题
理论上弹出的是11 但是。。。。。。。。。。。。。
161 0
js中递归调用返回值为undefined问题
|
JavaScript 前端开发
JavaScript中的隐含参数arguments
JavaScript中的隐含参数arguments
76 0
|
JSON JavaScript 安全
分分钟学会 JS AST,打造自己的编译器
抽象语法树是js代码另一种结构映射,可以将js拆解成AST,也可以把AST转成源代码。这中间的过程就是我们的用武之地。 利用 抽象语法树(AST) 可以对你的源代码进行修改、优化,甚至可以打造自己的编译工具。其实有点类似babel的功能。咱们就一起学习下怎么玩转 ast。
657 0
分分钟学会 JS AST,打造自己的编译器
|
JavaScript
js 外部调用 嵌套函数
js 外部调用 嵌套函数
71 0
js 外部调用 嵌套函数
|
自然语言处理 前端开发 JavaScript
用25行JavaScript语句实现一个简单的编译器
用25行JavaScript语句实现一个简单的编译器
137 0
|
JavaScript 前端开发 API
TypeScript 编译生成的 JavaScript 源代码里的 ɵcmp 属性
TypeScript 编译生成的 JavaScript 源代码里的 ɵcmp 属性
148 0
TypeScript 编译生成的 JavaScript 源代码里的 ɵcmp 属性