若检查所有类型节点(即checkNonElements==true),获取elem指定位置关系的紧邻节点,执行匹配函数,检查该节点是否符合要求,若符合返回true,否则返回false;
有些人或许会问,不是说是紧邻关系吗?那代码中为何要出现迭代获取这一过程呢?这是因为,个别浏览器会把节点文本之间的换行符看成是TextNode,故在处理过程中,需要跳过这些节点,直到下一个element节点。
4.1.2 参数
elem——待检查的单个节点元素。
context——执行整个选择器字符串匹配的上下文节点,大部分时候是没有用途。
xml——当前搜索对象是HTML还是XML文档,若是HTML,则xml参数为false。
4.2 若关系选择器是~或空格,则返回如下函数:
复制代码 代码如下:
//Check against all ancestor/preceding elements
function(elem, context, xml) {
var data, cache, outerCache, dirkey = dirruns + " " + doneName;
// We can't set arbitrary data on XML nodes, so they don't
// benefit from dir caching
if (xml) {
while ((elem = elem[dir])) {
if (elem.nodeType === 1 || checkNonElements) {
if (matcher(elem, context, xml)) {
return true;
}
}
}
} else {
while ((elem = elem[dir])) {
if (elem.nodeType === 1 || checkNonElements) {
outerCache = elem[expando] || (elem[expando] = {});
if ((cache = outerCache[dir])
&& cache[0] === dirkey) {
if ((data = cache[1]) === true
|| data === cachedruns) {
return data === true;
}
} else {
cache = outerCache[dir] = [ dirkey ];
cache[1] = matcher(elem, context, xml)
|| cachedruns;
if (cache[1] === true) {
return true;
}
}
}
}
}
};
4.2.1 功能
若检查的是XML文档,则其过程与4.1返回函数一致,见上述代码中if ( XML ) { ... }中大括号内的代码。
若是HTML文档,则根据matcher匹配当前元素,若匹配成功,返回true;否则返回false。
4.2.2 参数
elem——待检查的单个节点元素。
context——执行整个选择器字符串匹配的上下文节点,大部分时候是没有用途。
xml——当前搜索对象是HTML还是XML文档,若是HTML,则xml参数为false。
4.2.3 代码说明
内部变量
dirkey——缓存节点检测结果用的键。在一次执行过程中,若一个节点被检查过,则会在这个节点的dirkey属性(属性名称为dirkey的值)中记录下检测结果(true或false),那么在本次执行过程中,再次遇到该节点时,不需要再次检测了。之所以需要缓存,因为多个节点会存在同一个父节点或兄弟节点,利用缓存可以减少检测的次数,提高性能。
dirruns——每次执行通过matcherFromGroupMatchers组织的预编译代码时都会产生一个伪随机数,用以区别不同的执行过程。
doneName——每次执行addCombinator函数时,done变量都会加1,用以区别生成的不同的位置关系匹配函数。
cachedruns——用来记录本次匹配是第几个DOM元素。例如:div.map>span,有3个元素符合span选择器,则针对每个元素执行>匹配函数时,cachedruns依次为0、1、2。cachedruns的作用按照代码可以直接理解为在一个执行过程中,针对同一个元素使用elementMatchers进行匹配过程中,再次遇到同一个元素时,可以直接从获取不匹配的结果,但是,我想不出哪个情况下会发生这种事情。若有人遇到,请告知,多谢!
代码解释
复制代码 代码如下:
while ((elem = elem[dir])) {
if (elem.nodeType === 1 || checkNonElements) {
// 若elem节点的expando属性不存在,则赋予空对象,并同时赋予outerCache
// 若elem节点的expando属性存在,则将其值赋予outerCache
outerCache = elem[expando] || (elem[expando] = {});
/*
* 若outCache[dir]有值,且其第一个元素等于当前的dirkey,
* 则说明当前位置选择器在本次执行过程中已检测过该节点,执行if内的语句,从缓存中直接获取结果
* 若outCache[dir]不存在,或第一个元素不等于当前的dirkey,
* 则说明当前位置选择器在本次执行过程中还未检测过该节点,执行else内的语句,匹配节点并将结果放入缓存
*/
if ((cache = outerCache[dir])
&& cache[0] === dirkey) {
// 若缓存中检测结果等于true或cachedruns的值,则返回检测结果(非true皆为false),
// 否则继续循环获取上一个符合位置关系的节点进行匹配
if ((data = cache[1]) === true
|| data === cachedruns) {
return data === true;
}
} else {
// 将数组[ dirkey ]赋予outerCache[dir]及cache
cache = outerCache[dir] = [ dirkey ];
// 将匹配成功,将true赋予cache[1],否则将cachedruns的值赋予cache[1]
cache[1] = matcher(elem, context, xml)
|| cachedruns;
// 若匹配结果为true,则返回true,否则继续循环获取上一个符合位置关系的节点进行匹配
if (cache[1] === true) {
return true;
}
}
}
}
您可能感兴趣的文章: