DOM 树向下递归

发布于 2024-11-28 19:14:17 字数 800 浏览 1 评论 0原文

这是来自 Crockford 的 JavaScript:The Good Parts 的代码。

var results = [];

var walkDOM = function (node,func) {
        func(node);                     //What does this do?
        node = node.firstChild;
        while(node) {
            walkDOM(node,func);
            node = node.nextSibling;
        }

    };

我理解除了 func(node) 之外的代码。我想重点是在函数 func 中将 node 作为参数传递,但是浏览器如何以这种方式理解它呢? nodefunc 可以是任何东西——所以当调用该函数时,它可以读成这样:

walkDOM(document.body,function(att) {
          node.getAttribute(att);
          results.push(node);
          });

当传递 func 时,walkDOM 将处理 function(att) {...}(document.body)——这没有任何意义。那么为什么 Crockford 选择包含 func(node) 呢?

This is code from Crockford's JavaScript: The Good Parts.

var results = [];

var walkDOM = function (node,func) {
        func(node);                     //What does this do?
        node = node.firstChild;
        while(node) {
            walkDOM(node,func);
            node = node.nextSibling;
        }

    };

I understand the code except for func(node). I guess the point is to pass node as a parameter in function func, but how will the browser understand it this way? node and func could be anything--so when the function is called it could read like this:

walkDOM(document.body,function(att) {
          node.getAttribute(att);
          results.push(node);
          });

When func is passed, walkDOM will process function(att) {...}(document.body)--which wouldn't make any sense. So why has Crockford chosen to include func(node)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

累赘 2024-12-05 19:14:17

是的,这个树遍历函数是有意义的,因为:

  • 函数参数应该知道如何处理(任何)节点
  • 第一个调用参数应该是受支持的节点(例如,不是 document.body ,如果func 不知道如何处理它)

也就是说,这个算法对我来说仍然看起来不正确,因为它只探索第一个兄弟;其他兄弟姐妹将被简单地忽略。因此,我建议使用这种更传统的方法:

function walk(node, func) {
   var children = node.childNodes;
   for (var i = 0; i < children.length; i++)  // Children are siblings to each other
       walk(children[i], func);
   func(node);
}

请注意,版本是“深度优先”(即在处理子项之前不调用 call func() ),但我宁愿推荐它,因为 func 可能会改变节点。这样,父进程的处理将能够在发出可能不适当的更改之前考虑其已处理的子进程的最新状态。

Yes this tree traversal function makes sense since :

  • the function argument is supposed to know how to handle (any) nodes
  • the first call argument is supposed to be a supported node (not document.body for instance, if func doesn't know how to handle it)

That said, this algorithm still looks incorrect to me, as it only explores through the first sibling ; other siblings will be simply ignored. So I would recommend using this more traditional approach instead :

function walk(node, func) {
   var children = node.childNodes;
   for (var i = 0; i < children.length; i++)  // Children are siblings to each other
       walk(children[i], func);
   func(node);
}

Note that version is "deep first" (i.e. not calling call func() before processing children), but I'd rather recommend it since func is likely to change nodes. This way the processing of a parent will be able to consider the latest state of its already-processed children before issuing possibly un-appropriate changes.

╰ゝ天使的微笑 2024-12-05 19:14:17

在我看来,func 用于对树中的每个节点执行某些操作。

例如,如果我想提醒整个树中每个节点的标签名称:

walkDOM(document.body, function(node) {
    alert(node.tagName);
});

在您的示例函数中:

walkDOM(document.body,function(att) {
      node.getAttribute(att);
      results.push(node);
      });

...您已将 node 参数命名为 att,但这并不能神奇地生成属性的名称。我希望运行 node.getAttribute(att) 时出现“变量'node'未定义”,因为节点被设置为 att...没有该函数范围内的 node

Looks to me like the func is used for doing something to every node in the tree.

For example, if I wanted to alert the tag name for every node in the entire tree:

walkDOM(document.body, function(node) {
    alert(node.tagName);
});

In your example function:

walkDOM(document.body,function(att) {
      node.getAttribute(att);
      results.push(node);
      });

... you have named the node parameter to att, but that doesn't magically make in a name of an attribute. I would expect a "variable 'node' is not defined" when node.getAttribute(att) is ran, because node is being set to att... there is no node in that function's scope.

此生挚爱伱 2024-12-05 19:14:17

该行中的 func

func(node)

就是通常所说的回调函数。它是可供 walkDOM 函数使用的函数。使用更详细的函数名称可能会有意义:

var results = [];

var walkDOM = function (node, iCanBeCalledOnANode) {
    iCanBeCalledOnANode(node); // Will be called on every DOM element 
    node = node.firstChild;
    while(node) {
        walkDOM(node,func);
        node = node.nextSibling;
    }

};

希望这可以帮助您解决问题。

The func that's in the

func(node)

line is what is typically known as a callback function. It a function that is available for use by the walkDOM function. It might make sense with a more verbose function name:

var results = [];

var walkDOM = function (node, iCanBeCalledOnANode) {
    iCanBeCalledOnANode(node); // Will be called on every DOM element 
    node = node.firstChild;
    while(node) {
        walkDOM(node,func);
        node = node.nextSibling;
    }

};

Hope this clears things up for you.

甜点 2024-12-05 19:14:17

Crockford 的代码将回调传递给 walkDOM,它可以通过多种方式使用来处理传递给它的参数。

一个示例是返回具有指定 tagName 的所有 DOM 元素的计数的方法:

var getTagNameCount = function(tagName) {
    var count = 0;
    walkDOM(document.body, function(node) {
       if (node.tagName === tagName) {
          count++;
       }
    });
    return count;
};

Crockford's code is passing a callback to walkDOM which can be used in many ways to process the arguments passed to it.

An example could be a method which returns the count of all DOM elements with the specified tagName:

var getTagNameCount = function(tagName) {
    var count = 0;
    walkDOM(document.body, function(node) {
       if (node.tagName === tagName) {
          count++;
       }
    });
    return count;
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文