遍历DOM

时间:2015-08-31 04:58:18

标签: javascript recursion refactoring

@oriol为我今天正在处理的问题提供了一个惊人的两行递归解决方案。

function numOccurencesRecursive(arr, val) {
  if (!arr.length) return 0;
  return (arr[0] === val ? 1 : 0) + numOccurencesRecursive(arr.slice(1), val);
}

我受到启发,重构了我昨天写的一些spagetti-ish代码:

//returns a boolean
    function containsFiveOrMoreDivs(domElement) {
      var count = 0;

  function doCount(domElement) {
    if (domElement && domElement.tagName === "DIV") {
      count++;
    }

    if (count >= 5) {
      return true;
    }

    if (domElement.hasChildNodes()) {
      var children = domElement.childNodes;
      for (var i = 0; i < children.length; i++) {
        if (doCount(children[i])) {
          return true
        }
      };
    };

    return false;
  }

  return doCount(domElement)
}
containsFiveOrMoreDivs(document);

这是尝试:

function containsFiveOrMoreDivsPureRecursion(domElement) {
  if (!domElement && domElement.tagName !== "DIV") {
    return 0;
  }
  return (domElement.tagName === "DIV" ? 1 : 0) + containsFiveOrMoreDivsPureRecursion(domElement.childNodes()); //?
}

如何在此版本中递归遍历所有子节点?我正在做什么?

1 个答案:

答案 0 :(得分:0)

使用递归,你应该记得返回1种类型的值,但是你想要返回一个布尔值但是你希望你的函数也返回计数。这确实使事情复杂化。

这是一个递归函数来计算元素类型

function countElements(domElement, elementType) {
    count = (domElement && domElement.tagName === elementType.toUpperCase());

    if (domElement.hasChildNodes()) {
      for (var i = 0; i < domElement.childNodes.length; i++) {
        count += countElements(domElement.childNodes[i], elementType); 
      };
    };

    return count;
}

你可以像这样使用它来达到你想要的效果。

countElements(document, 'div') >= 5

但是,这可能不是最有效的方法,因为它会遍历整个DOM树,但你真正想要的是它在你击中5个元素时停止。

function containsFiveOrMoreDivsPureRecursion(domElement, elementType) {
    var count = 0;

    function countElements(domElement, elementType) {
        count += (domElement && domElement.tagName === elementType.toUpperCase());

        if (count >= 5) return count;

        if (domElement.hasChildNodes()) {
          for (var i = 0; i < domElement.childNodes.length; i++) {
            countElements(domElement.childNodes[i], elementType); 
          };
        };

        return count;
    }


    return countElements(domElement, elementType) >= 5;
}

在这个例子中,你需要在函数之外保留一个变量(因此它不是真正的纯递归)来跟踪计数并能够返回一个布尔值。