我对这个递归 JavaScript 函数做错了什么?

发布于 2024-10-18 13:20:23 字数 3041 浏览 1 评论 0原文

这是整个页面:

<html>
<head>
        <script type="text/javascript" src="/jquery.js"></script>
        <script type="text/javascript" src="/json2.js"></script>
        <script type="text/javascript">
                function buildList(point) {
                        if ( !point )
                                return [];
                        children = [];
                        lis = point.children('li');
                        for (index = 0; index < lis.length; index++) {
                                id = $(lis[index]).attr('id');
                                parts = id.split('-');
                                title = $(lis[index]).children('div').text();
                                newObj = {
                                        id: parts[1],
                                        mtype: parts[0],
                                        label: title
                                }
                                ol = $(lis[index]).children('ol');
                               // if (ol.length == 1) {
                               //         newObj['childobjects'] = buildList(ol);
                               // }
                                children.push(jQuery.extend(true, {}, newObj));
                        }
                        return children;
                }
                $(function() {
                        obj = buildList( $('#menu-top') );
                        alert( JSON.stringify(obj) );
                });
        </script>
</head>
<body>
<ol id="menu-top" class="sortable ui-sortable">
        <li id="entry-16608">
                <div>Test item 1</div>
                <ol>
                        <li id="entry-16607" ">
                                <div>News, links and random thoughts</div>
                        </li>
                </ol>
        </li>
        <li id="entry-16609">
                <div>How a data retention mandate will likely lead to de facto censorship in the US</div>
        </li>
        <li id="entry-16579">
                <div>Git cheat sheet</div>
        </li>
</ol>
</body>
</html>

当我注释掉递归调用时,我的 JSON 看起来像这样:

[
   {
      "id":"16608",
      "mtype":"entry",
      "label":"Test item 1"
   },
   {
      "id":"16609",
      "mtype":"entry",
      "label":"How a data retention mandate will likely lead to de facto censorship in the US"
   },
   {
      "id":"16579",
      "mtype":"entry",
      "label":"Git cheat sheet"
   }
]

当我取消注释代码时,JSON 看起来像这样:

[
   {
      "id":"16607",
      "mtype":"entry",
      "label":"News, links and random thoughts"
   },
   {
      "id":"16607",
      "mtype":"entry",
      "label":"News, links and random thoughts"
   }
]

我猜这是我对更详细的细节一无所知的结果JavaScript 如何处理作用域和递归,但我不知道在这里要做什么。

Here is the entire page:

<html>
<head>
        <script type="text/javascript" src="/jquery.js"></script>
        <script type="text/javascript" src="/json2.js"></script>
        <script type="text/javascript">
                function buildList(point) {
                        if ( !point )
                                return [];
                        children = [];
                        lis = point.children('li');
                        for (index = 0; index < lis.length; index++) {
                                id = $(lis[index]).attr('id');
                                parts = id.split('-');
                                title = $(lis[index]).children('div').text();
                                newObj = {
                                        id: parts[1],
                                        mtype: parts[0],
                                        label: title
                                }
                                ol = $(lis[index]).children('ol');
                               // if (ol.length == 1) {
                               //         newObj['childobjects'] = buildList(ol);
                               // }
                                children.push(jQuery.extend(true, {}, newObj));
                        }
                        return children;
                }
                $(function() {
                        obj = buildList( $('#menu-top') );
                        alert( JSON.stringify(obj) );
                });
        </script>
</head>
<body>
<ol id="menu-top" class="sortable ui-sortable">
        <li id="entry-16608">
                <div>Test item 1</div>
                <ol>
                        <li id="entry-16607" ">
                                <div>News, links and random thoughts</div>
                        </li>
                </ol>
        </li>
        <li id="entry-16609">
                <div>How a data retention mandate will likely lead to de facto censorship in the US</div>
        </li>
        <li id="entry-16579">
                <div>Git cheat sheet</div>
        </li>
</ol>
</body>
</html>

When I comment out the recursive call, my JSON looks like this:

[
   {
      "id":"16608",
      "mtype":"entry",
      "label":"Test item 1"
   },
   {
      "id":"16609",
      "mtype":"entry",
      "label":"How a data retention mandate will likely lead to de facto censorship in the US"
   },
   {
      "id":"16579",
      "mtype":"entry",
      "label":"Git cheat sheet"
   }
]

When I uncomment the code, the JSON looks like this:

[
   {
      "id":"16607",
      "mtype":"entry",
      "label":"News, links and random thoughts"
   },
   {
      "id":"16607",
      "mtype":"entry",
      "label":"News, links and random thoughts"
   }
]

I'm guessing this is the result of ignorance on my part about the finer details of how JavaScript handles scoping and recursion, but I'm at a loss as to what to do here.

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

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

发布评论

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

评论(2

鹊巢 2024-10-25 13:20:23

是的,这是一个范围问题。您忘记将 var 放在 all 变量前面。这使得变量成为全局变量,这意味着每个函数调用都可以访问相同的变量(并覆盖它们)。

请参阅修复版本: http://jsfiddle.net/fkling/uYXYh/

您可以进一步改进通过使用更多 jQuery 方法来编写代码:

function buildList(point) {
    if (!point) return [];
    var children = [];
    point.children('li').each(function() {
        var parts = this.id.split('-');
        var newObj = {
            id: parts[1],
            mtype: parts[0],
            label: $(this).children('div').text()
        };
        var $ol = $(this).children('ol');
        if ($ol.length == 1) {
            newObj['childobjects'] = buildList($ol);
        }
        children.push(jQuery.extend(true, {}, newObj)); // not sure why you are
                                                        // doing this instead of
                                                        // children.push(newObj)
    });
    return children;
}

DEMO

Yes, it is a scope problem. You forgot to put var in front of all variables. This makes the variables global, meaning each function call has access to the same variables (and is overwriting them).

See the fixed version: http://jsfiddle.net/fkling/uYXYh/

You could further improve the code by making use of more jQuery methods:

function buildList(point) {
    if (!point) return [];
    var children = [];
    point.children('li').each(function() {
        var parts = this.id.split('-');
        var newObj = {
            id: parts[1],
            mtype: parts[0],
            label: $(this).children('div').text()
        };
        var $ol = $(this).children('ol');
        if ($ol.length == 1) {
            newObj['childobjects'] = buildList($ol);
        }
        children.push(jQuery.extend(true, {}, newObj)); // not sure why you are
                                                        // doing this instead of
                                                        // children.push(newObj)
    });
    return children;
}

DEMO

手心的海 2024-10-25 13:20:23

看来 index 被声明为全局变量,并且在每次调用 buildList 时都会发生变化。我认为这是你的问题(但也许你是为了我没有看到的事情而故意这样做的)。尝试将您的 for 语句更改为:

for(var index=0; index < lis.length; index++){
    // ...
}

It appears that index is being declared as a global variable, and is getting mutated on each call to buildList. I think that's your problem (but maybe you're doing that on purpose for something that I'm not seeing). Try changing your for statement to:

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