1

再帰がどのように機能するかを理解しようとしています。以下のコードは、HTMLドキュメントのノードをウォークスルーします。関数を呼び出し、各ノードに順番に渡します。誰かがそれがどのように段階的に行われているのか説明できますか?ありがとう。

var walk_the_DOM = function walk(node, func) {
    func(node);
    node = node.firstChild;
    while (node) {
        walk(node, func);
        node = node.nextSibling;
    }
}
4

3 に答える 3

2

最初のステートメントは関数定義です。

var walk_the_DOM = function walk(node, func) {
    ...
};

これにより、 に機能が割り当てられwalk_the_DOMます。nodeこの関数は、との 2 つのパラメータを取りますfuncnodeは作業対象のノードで、funcは適用対象の機能ですnode

関数の最初の行はfunc(node);. これは基本的に、渡された関数を に適用していることを意味しますnode。たとえば、次のように呼び出した場合walk_the_DOM:

walk_the_DOM(root, function(node) {
    console.log(node);
});

あなたは電話しているでしょう

function(node) {
    console.log(node);
}

ツリー内のすべてのノードを出力する効果として、すべてのノードで。

次の行node = node.firstChild;は基本的に、nodeを最初の子に再割り当てします。これを行う必要があるのは、現在のノードの各子を調べる必要があるためです。もちろん、それらの子の子も確認する必要がありますが、その部分については後で説明します。

これでwhileループに入ります。このwhileループの条件は just です。これは、が定義されていないか未定義であるwhile(node)限り、ループが実行されることを意味します。前のステートメントでは、 を行いました。現在のノードに子がない場合はどうなりますか? その後は null になるため、ループには入りません。そこから外れて関数を終了します (この部分を覚えておいてください。現在のノードに子がない場合は関数を終了します。これは、再帰関数の停止条件として知られています)。nodenullnode = node.firstChildnode.firstChild

ループ内で、while再帰呼び出しを行います: walk(node, func);. ここで起こっていることは一瞬無視して、次の行に進みましょう: node = node.nextSibling;. ここでは、ノードの次の兄弟を変数に割り当てていますnode。実際には、このノードの兄弟を繰り返し処理しています。ノードに他の兄弟がない場合 (つまり、親ノードに子が 1 つしかない場合) はどうなるでしょうか。その後nodenull になり、ループから抜け出します。

では、再帰呼び出しに戻りましょうwalk(node, func)。再帰呼び出しでは、関数自体を呼び出します。これは、関数の動作がこの反復の場合とまったく同じであることを意味します。この時点で、「でも、これは永遠に実行されるということではないのですか?」と思うかもしれません。しかし、そうはなりません!なんで?先ほどの停止条件を覚えていますか? ある時点で、子を持たないノードを渡します。これは、再帰呼び出しが終了して次の行に戻ることを意味します (node = node.nextSibling)、実行は正常に進行します。DOM をツリー (ツリー) と考えると、これが意味することは、1 つのブランチを可能な限り下に移動し、最後に到達したら 1 レベル上に戻り、チェックして確認することです。他に兄弟がいる場合。ある場合は、その枝を可能な限り下ります。そうでない場合は、もう 1 レベル上に戻り、再度チェックを行います。このようにして、DOM ツリー全体をトラバースできます。

于 2012-11-05T21:04:03.333 に答える
1

このコードが行うことはfunc、サブツリーのすべての要素に対して関数を実行することです。

ノードを walk 関数に渡します。そのノードのすべての子を取得し、それらに対して walk メソッドを呼び出します。

すべてのノードはサブツリーであるかのように見ることができ、walk関数を呼び出すたびに小さなサブツリー ソリューションが解決されます。それwalksは実際には何もしないからです。

最終的にnode.firstChildはになりnull、JavaScriptでnull比較されるため、ループに入らないだけです。false

于 2012-11-05T20:50:24.697 に答える
0
// 1. you define a function
var walk_the_DOM = function walk(node, func) { 

    // 4. you call your callback
    func(node);
    // func.call(node); // inside func, 'this' will be node

    // 5. you get the first child
    node = node.firstChild;

    // 6. as long as 'node' is, so not false, 0, null, undefined or '',
    while (node) {

        // 7. recurse the function, jumps to step 4 (in a new closure of walk)
        walk(node, func);
        // walk_the_DOM(node, func);

        // 8. get the next child, going to step 6
        node = node.nextSibling;
    }

    // 9. no more siblings, current walk returns

}; // 2. the function is defined, by name 'walk' and in var 'walk_the_DOM'!

// 3. you call the function once, with an anonymous callback
walk(document, function (currentNode) { });
// walk_the_DOM(document, function (currentNode) { });
于 2012-11-05T21:01:32.007 に答える