CSS选择器从右向左的匹配规则
CSS选择器从右向左的匹配规则
下面这个栗子,CSS选择器它是如何工作的?
.mod-nav h3 span {font-size: 16px;}
如果不知道匹配规则,可能的理解是从左向右匹配:先找到.mod-nav,然后逐级匹配h3、span,在这个过程中如果遍历到叶子节点都没有匹配就需要回溯,继续寻找下一个分支。
但事实上,CSS选择器的读取顺序是从右向左。
还是上面的选择器,它的读取顺序变成:先找到所有的span,沿着span的父元素查找h3,中途找到了符合匹配规则的节点就加入结果集;如果直到根元素html都没有匹配,则不再遍历这条路径,从下一个span开始重复这个过程(如果有多个最右节点为span的话)。
在某条CSS规则下(比如.mod-nav h3 span),会形成一条符合规则的索引树,树由上至下的节点是规则中从右向左的一个个选择符匹配的节点。索引树遍历的具体过程可以看寒冬大大的一段视频。
为什么从右向左的规则要比从左向右的高效?

假如DOM的结构如上图,匹配规则是.mod-nav h3 span。
若从左向右的匹配,过程是:从.mod-nav开始,遍历子节点header和子节点div,然后各自向子节点遍历。在右侧div的分支中,最后遍历到叶子节点a,发现不符合规则,需要回溯到ul节点,再遍历下一个li-a,假如有1000个li,则这1000次的遍历与回溯会损失很多性能。
再看看从右至左的匹配:先找到所有的最右节点span,对于每一个span,向上寻找节点h3,由h3再向上寻找class=mod-nav的节点,最后找到根元素html则结束这个分支的遍历。
很明显,两种匹配规则的性能差别很大。之所以会差别很大,是因为从右向左的匹配在第一步就筛选掉了大量的不符合条件的最右节点(叶子节点);而从左向右的匹配规则的性能都浪费在了失败的查找上面。
当然这是比较明显情况,如果在叶子上存在多个不符合条件的span,从右向左的规则也会走一些弯路(这时就需要优化CSS选择器了)。但平均来说它还是更高效,因为大多时候,一个DOM树中,符合匹配条件的节点(如.mod-nav h3 span)远远远远少于不符合条件的节点。
jQuery从1.3版本开始使用的Sizzle引擎,它按照了CSS选择器的匹配规则(从右至左)进行DOM元素的查找与匹配(当然其中做了很多优化),性能得到了很大的提升。
欢迎批评指正。
[创新工场2014] 2014创新工场校园招聘笔试题
继上一篇博文《[创新工厂2014]回文修复》后,继续推出第二道创新工厂的笔试算法题~
对于非负数列a1、a2、......、an,在数轴上做垂线连接点(i,0)和(i,ai)。选择这样的两条线和x轴可以形成一个容器,我们以面积代表所装的水,求以这种方式构成的容器能装的最大面积。比如选择a2=3、a5=6,则所装的面积为9。
分析:
这道题实际上的意思是:对于一个给定的序列,求abs(i-j)*min(a[i],a[j])的最大值!
先对序列按照高度排序,然后按照排序后的顺序进行枚举,枚举过的就做标记,表示已经访问过了,保证了当前的节点,是序列里的最小高度的板,那么以这个板为边界能装的最大的水,肯定就是当前序列的最左边,或者最右边,因为没有其他板比当前板更矮了,分别计算,并且update最大值。
如果当前这个节点就是边界,且已经访问过(即比当前的节点的高度更小),那么就要对L和R进行收缩,保证L和R是当前节点能构成最大容器的最远边界。
代码如下:
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <limits.h>
using namespace std;
#define max(a,b) a>b?a:b
typedef struct Pair{
int i;
int ai;
}Pair;
Pair p[101];
int n;
int flag[101];
bool cmp(Pair a,Pair b)
{
if(a.ai<b.ai)
return true;
else
return false;
}
int main()
{
freopen("b3.in","r",stdin);
freopen("b3.out","w",stdout);
int maxRes;
int L,R;
while(scanf("%d",&n)!=EOF)
{
memset(flag,0,sizeof(flag));
maxRes = INT_MIN;
for(int i=0; i<n; i++)
{
scanf("%d",&p[i].ai);
p[i].i = i;
}
sort(p,p+n,cmp);
L=0;
R=n-1;
for(int i=0; i<n; i++)
{
flag[p[i].i] = 1;
maxRes = max(maxRes,abs(L-p[i].i)*p[i].ai);
maxRes = max(maxRes,abs(R-p[i].i)*p[i].ai);
if(p[i].i==L)
{
while(flag[L]==1) L++;
}
if(p[i].i==R)
{
while(flag[R]==1) R--;
}
}
printf("%d\n",maxRes);
}
return 0;
}
如果有错误的地方,还望大家及时指出,谢谢~
CSS选择器从右向左的匹配规则的更多相关文章
- 正则表达式从右往左进行匹配(Regex)
#匹配最末两位为数字 $x=New-Object regex ('\d{2}','RightToLeft') #$x.RightToLeft $x.Match('abcd22') 结果:
- CSS选择器性能分析
写了几篇关于js的博客,也是关于性能的,现在,我觉得有必要那css来认真分析一下了.之前只是看别人这么写就跟着写,但是没有去研究这样写或者是不是正确的写法,性价比怎么样,渲染的效率好么!这些都没有考虑 ...
- css选择器选择顺序是从右往左的,为什么?
https://segmentfault.com/q/1010000000713509 为什么 CSS 选择器解析的时候是从右往左? CSS 的后代选择器本身就是一种在标准里面不那么推荐的方式. 首先 ...
- CSS选择器、优先级与匹配原理
为了分析Bootstrap源码,所以的先把CSS选择器相关的东东给巩固好 废话就不多说了 CSS 2.1 selectors, Part 1 计算指定选择器的优先级:重新认识CSS的权重 标签的权值为 ...
- CSS选择器、优先级与匹配原理(转)
CSS选择器.优先级与匹配原理 导航 为了分析Bootstrap源码,所以的先把CSS选择器相关的东东给巩固好 废话就不多说了 CSS 2.1 selectors, Part 1 计算指定选择器的优先 ...
- 如何提升 CSS 选择器性能
CSS 选择器性能损耗来自? CSS选择器对性能的影响源于浏览器匹配选择器和文档元素时所消耗的时间,所以优化选择器的原则是应尽量避免使用消耗更多匹配时间的选择器.而在这之前我们需要了解CSS选择器匹配 ...
- CSS选择器渲染效率
1 浏览器如何识别你的选择器 首先我们需要清楚,浏览器是如何读取选择器,以识别样式,并将相应的样式附于对应的HTML元素,达到美化页面的效果.Chris Coyier曾在<Efficiently ...
- CSS选择器的优化
前面花了几个篇幅着重介绍了CSS的选择器的使用,我将其分成三个部分:CSS基本选择器.CSS属性选择器以及CSS伪类选择器.那么今天我主要想和大家一起来学习——CSS选择器方面的性能优化.因为对性能这 ...
- 提升 CSS 选择器性能的方法
CSS 选择器性能损耗来自? CSS选择器对性能的影响源于浏览器匹配选择器和文档元素时所消耗的时间,所以优化选择器的原则是应尽量避免使用消耗更多匹配时间的选择器.而在这之前我们需要了解CSS选择器匹配 ...
随机推荐
- cralwer_爬虫代理中心的简要设计
代理中心: 简单讲: 精细化控制限制资源的使用,保证有限资源的充分利用及有效性.支持动态增减,实时更新. 需求 rest api提供请求输入与输出 客户端使用代理心跳接收,用于更新代理的使用次数,被占 ...
- Windbg Extension NetExt
Windbg Extension NetExt 摘要 : 在使用WINDBG做debugging的时候,需要一个好的工具帮助进行数据分析. 最常见的extension包括SOS, PSSCOR. N ...
- Humming Bird A20 SPI2驱动编译
Humming Bird A20 SPI2使用编译 Yao.GUET 2014-07-17,请注明出处:http://blog.csdn.net/Yao_GUET A20上带有4个spi接口,因为Hu ...
- 基于protobuf的RPC实现
可以比较使用google protobuf RPC实现echo service可见.述. google protobuf仅仅负责消息的打包和解包.并不包括RPC的实现.但其包括了RPC的定义.如果有以 ...
- 寻找单向链表的倒数第k个节点
题目: 输入一个单向链表,输出这个单向链表的倒数第k个节点 template<class T> class ListNode { public: T Data; ListNode<T ...
- SQL Server 2012的附件失败,与硬链接的问题
1.我在系统上做了硬链接,也就是把C盘的某个目录,映射为D盘. 2.把数据库文件mdf和ldf放入D盘.结果,SQL Server的企业管理器,无法从D盘里加载mdf或ldf文件,并且在目录下无法显示 ...
- 快速构建Windows 8风格应用30-应用生命周期管理
原文:快速构建Windows 8风格应用30-应用生命周期管理 引言 Windows 8 中可以启动多个应用并在其中切换,我们没有必要担心降低系统速度或消耗电池电量. 因为系统会自动挂起(有时会终止) ...
- jquery的使用 关于 option ,append,attr,val()等的使用
//遍历option和添加.移除option function changeShipMethod(shipping){ var len = $("select[@name=ISHIPTYPE ...
- Linux下使用Photorec恢复误格U盘
photorec包含在testdisk软件包中, 所以直接通过包管理器直接安装testdisk安装即可. 使用root权限来运行软件,在终端键入 [shell] photorec [/shell] 然 ...
- 使用sqlldr向Oracle导入大的文本(txt)文件
我们有多种方法可以向Oracle数据库里导入文本文件,但如果导入的文本文件过大,例如5G,10G的文本文件,有些方法就不尽如意了,例如PLSQL Developer中的导入文本功能,如果文本文件过大, ...