Рекурсия по дереву DOM - PullRequest
       1

Рекурсия по дереву DOM

2 голосов
/ 07 августа 2011

Это код из Крокфордского JavaScript: Хорошие части.

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).Я думаю, смысл в том, чтобы передать node в качестве параметра в функцию func, но как браузер поймет это таким образом?node и func могут быть чем угодно - поэтому при вызове функции она может выглядеть следующим образом:

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

Когда передано func, walkDOM обработает функцию (att) {...} (document.body) - что не имеет никакого смысла.Так почему же Крокфорд решил включить func (node)?

Ответы [ 4 ]

8 голосов
/ 13 февраля 2013

Да, эта функция обхода дерева имеет смысл, поскольку:

  • аргумент функции должен знать, как обрабатывать (любые) узлы
  • предполагается, что первый аргумент вызова является поддерживаемым узлом (например, не 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, вероятно, изменит узлы. Таким образом, обработка родителя сможет учитывать последнее состояние его уже обработанных потомков, прежде чем вводить, возможно, неподходящие изменения.

5 голосов
/ 07 августа 2011

Похоже, что 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), потому что для узла устанавливается значение att ... в области действия этой функции нет node.

3 голосов
/ 19 июля 2015

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

};

Надеюсь, это прояснит для вас.

0 голосов
/ 14 апреля 2017

Код Крокфорда передает обратный вызов в walkDOM, который может использоваться многими способами для обработки переданных ему аргументов.

Примером может служить метод, который возвращает количество всех элементов DOM с указанным tagName:

var getTagNameCount = function(tagName) {
    var count = 0;
    walkDOM(document.body, function(node) {
       if (node.tagName === tagName) {
          count++;
       }
    });
    return count;
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...