使用递归重新实现getElementsByClassName - Javascript

时间:2015-09-16 16:52:33

标签: javascript html arrays recursion

我目前正致力于学习递归,并尝试通过使用递归遍历DOM来重新实现getElementsByClassName函数。我终于觉得我已经掌握了这些概念,但是当我将匹配元素推入结果数组时,我遇到了问题。继承我的代码:

var getElementsByClassName = function(className){
  var results = [];
  var domWalker = function(node) {
    for (var i=0; i<node.children.length; i++) {
        if (node.children[i].classList.contains(className)) {
            console.log(node.children[i])
            results.push(node.children[i])
        }

        if (node.children[i].children.length > 0) {
            domWalker(node.children[i])
        }

    }
    return results;
  };
  domWalker(document.body);
  console.log(results)
};

基本上,我需要结果数组来保存它以HTML格式找到的匹配元素,如下所示:

[<div class="title"></div>, <button class="click"></button>]

...当我将这些元素推送到我的结果数组中时,它们会更改为:[div.title, button.click]格式。

我在console.log的调用之上添加了results.push语句,以查看结果是否以正确的格式显示,然后再将它们推送到数组中。推送到数组的结果是我正在寻找的结果,它们只是以错误的格式出现。

为什么push会导致我的结果格式发生变化?如何解决此问题?

2 个答案:

答案 0 :(得分:0)

node.children [i]拥有对HTML元素的引用

console.log()应用隐含的.toString()方法给出你看到的内容。

你需要这个额外的代码(扩展到你找到的所有可能的tagNames):

var el = node.children[i];
el = '<' + el.tagName + (el.className ? ' class="' + el.className + '"': '') + '/>';
console.log(el);
results.push(el);

答案 1 :(得分:0)

我曾经解决过这个问题。虽然我还没有通读你的解决方案,但这是我的,有很多评论。我希望它有所帮助:

var getElementsByClassName = function(className, node){
  // The empty results array, which gets created whenever the function is
  // called. 
  var results = [];

  // Default the node to the document's body if it isn't set. This way, we can
  // call the function recursively with child elements, but never have to
  // worry about it the first time around.
  node = node || document.body;

  // If the node contains the class list in question, let's push it into the
  // results array.
  if (node.classList && node.classList.contains(className)) {
    results.push(node);
  }

  // Now, let's fetch the child nodes of the current node.
  var children = node.childNodes;

  // If child nodes exist, then we proceed here.
  if (children) {
    // Let's now loop over all child nodes of the current node in question. This
    // way, we'll be able to perform checks on each child node.
    for (var i = 0; i < children.length; i++) {
      // Fetch the i child node.
      var child = children[i];

      // At this point, we want to pass the child node back into the function,
      // implementing recursion. The same checks above will occur, and if the
      // node has the class name, it will be added to the results array from
      // that function call.
      //
      // This returns an array, and we need to merge it with the current set
      // of results, so we concat it.
      //
      // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat
      results = results.concat(getElementsByClassName(className, child));
    }
  }

  // We then return the combined results array from all the recursive function
  // calls!
  return results;
};
相关问题