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 against closest ancestor/preceding element
 function(elem, context, xml) {
  while ((elem = elem[dir])) {
   if (elem.nodeType === 1 || checkNonElements) {
    return matcher(elem, context, xml);
   }
  }
 } :

// 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;
      }
     }
    }
   }
  }
 };
}

2、功能

生成关系选择器的执行函数。

3、参数

matcher——位置关系前连续的过滤选择器匹配函数数组,该函数用于匹配通过位置关系获得的节点是否符合选择器要求。在实际执行过程中,该函数可能是关系选择器前已生成的elementMatcher(matchers)。例如:div.map>span,在Sizzle编译遇到>时,会将div.map的编译函数作为第一个参数调用addCombinator函数,用以检查获取的span父节点是否满足div.map这两个条件。

combinator——关系选择器对应Expr.relative中的值,Expr.relative中各种关系选择器的值如下。使用该参数的first属性来确定返回的是仅检查紧邻对象的函数还是遍历所有可能对象的函数。将通过如下代码:elem = elem[dir],获取指定位置关系的节点,其中dir等于combinator.dir。

复制代码 代码如下:


Expr.relative : {
 ">" : {
  dir : "parentNode",
  first : true
 },
 " " : {
  dir : "parentNode"
 },
 "+" : {
  dir : "previousSibling",
  first : true
 },
 "~" : {
  dir : "previousSibling"
 }
}

base——该参数与combinator.dir一起,确定变量checkNonElement的值,代码如下。该值从字面理解为当前检查的是非DOM元素,就是当elem.nodeType!=1的时候,若该值为true,则会执行匹配函数,否则结束本次循环。

4、返回函数

4.1 若关系选择器是>或+,则返回如下函数:

复制代码 代码如下:


function(elem, context, xml) {
 while ((elem = elem[dir])) {
  if (elem.nodeType === 1 || checkNonElements) {
   return matcher(elem, context, xml);
  }
 }
}

4.1.1 功能
若检查element类型节点(即checkNonElements==false),迭代获取elem指定位置关系的第一个element类型节点(elem.nodeType == 1),执行匹配函数,检查该节点是否符合要求,若符合返回true,否则返回false;

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wgjpdg.html