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的流程

测试,高级浏览器

参考对照学习

Sizzle


时间: 2024-07-30 05:03:44

sizzle编译函数的相关文章

通过编译函数库来学习GCC

一.基本概念 什么是库 在windows平台和linux平台下都大量存在着库. 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不同(主要是编译器.汇编器和连接器的不同),因此二者库的二进制是不兼容的. 本文仅限于介绍linux下的库. 库的种类 linux下的库有两种:静态库和共享库(动态库). 二者的不同点在于代码被载入的时刻不同. 静态库的代码在编译过程中已经被载入可执行程序,因此体积较大. 共享库的代码是在可执行程序运行时才载入

学习制作iOS程序第三天:创建全局变量,预编译函数等、优化TabBarController、加入Bugly崩溃日志、解决键盘覆盖文本框的问题

十一:创建Define定义文件和pch预处理文件 1.在Define目录里创建Const.h文件,用于保存一些常用的宏命令 #define CURRENT_APPID @"" #define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) #define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) #define IS_

jQuery-1.9.1源码分析系列(三) Sizzle选择器引擎——编译原理

这一节要分析的东东比较复杂,篇幅会比较大,也不知道我描述后能不能让人看明白.这部分的源码我第一次看的时候也比较吃力,现在重头看一遍,再分析一遍,看能否查缺补漏. 看这一部分的源码需要有一个完整的概念后去看才比较容易看懂,所以我们先把整个编译的原理阐述以后再进行解析. 还是以上次的那个CSS选择器为例:#chua > a + .group labe[for="age"].按照我们正常解析CSS的思路从右往左解析,解析之前词法分析完毕,词法分析结果保存在tokens中. 正常的思路:

jQuery选择器代码详解(八)——addCombinator函数

function addCombinator(matcher, combinator, base) 1.源码 function addCombinator(matcher, combinator, base) { var dir = combinator.dir, checkNonElements = base && dir === "parentNode", doneName = done++; return combinator.first ? // Check a

Sizzle选择器引擎介绍

一.前言 Sizzle原来是jQuery里面的选择器引擎,后来逐渐独立出来,成为一个独立的模块,可以自由地引入到其他类库中.我曾经将其作为YUI3里面的一个module,用起来畅通无阻,没有任何障碍.Sizzle发展到现在,以jQuery1.8为分水岭,大体上可以分为两个阶段,后面的版本中引入了编译函数的概念,Sizzle的源码变得更加难读.不再兼容低版本浏览器,而且看起来更加零散.本次阅读的是Sizzle第一个阶段的最终版本jQuery1.7,从中收获颇多,一方面是框架设计的思路,另外一方面是

jQuery源码学习:Sizzle

本文所有讨论均基于jQuery版本3.1.1,官网http://jquery.com/. 一 简介 Sizzle是用javascript实现的CSS selector engine,官网见https://sizzlejs.com/.官网上给出的Public API是 Sizzle( String selector[, DOMNode context[, Array results]] ) returns (Array): All elements matching the selector 由于

jQuery中的Sizzle引擎分析

我分析的jQuery版本是1.8.3.Sizzle代码从3669行开始到5358行,将近2000行的代码,这个引擎的版本还是比较旧,最新的版本已经到v2.2.2了,代码已经超过2000行了.并且还有个专门的Sizzle主页. 从一个demo开始,HTML代码如下: <div id="grand_father"> <div id="father"> <div id="child1" class="child&

Sizzle一步步实现所有功能(层级选择)

第二步:实现Sizzle("el,el,el..."),Sizzle("el > el"),Sizzle("el el"),Sizzle("el + el"),Sizzle("el ~ el") 1 (function( window ){ 2 3 var arr = []; 4 var select ; 5 var Expr; 6 var push = arr.push; 7 // http://w

jQuery选择器引擎和Sizzle介绍

一.前言 Sizzle原来是jQuery里面的选择器引擎,后来逐渐独立出来,成为一个独立的模块,可以自由地引入到其他类库中.我曾经将其作为YUI3里面的一个module,用起来畅通无阻,没有任何障碍.Sizzle发展到现在,以jQuery1.8为分水岭,大体上可以分为两个阶段,后面的版本中引入了编译函数的概念,Sizzle的源码变得更加难读.不再兼容低版本浏览器,而且看起来更加零散.本次阅读的是Sizzle第一个阶段的最终版本jQuery1.7,从中收获颇多,一方面是框架设计的思路,另外一方面是