【问题标题】:Why am I only getting the last item from javascript for loop? [duplicate]为什么我只从 javascript for 循环中获取最后一项? [复制]
【发布时间】:2014-05-08 20:27:29
【问题描述】:

我已尝试搜索此问题,并发现许多人的 for 循环有问题,并且它只返回最后一个元素。尽我所能,我只是不明白我在这里做错了什么。

我真的是 Javascript 新手,所以我认为我遇到了 闭包 的问题?我正在写的应该是从 Urbandictionary API 返回的 JSON 中获取一些数据。 JSON 提取有效,但我用该数据构建 div 的 for 循环无法正常工作。

function word(term, def, example)
    {
      this.term = term;
      this.def = def;
      this.example = example;
     }

var lexicon = ['highway+salute', 'score', 'ya+heard+me', 'utz'];

var color = ['reddy', 'bluey', 'greeny', 'tanny', 'darky'];

for (var i = 0; i < lexicon.length; i++) {

$.getJSON('http://api.urbandictionary.com/v0/define?term=' + lexicon[i],
    function(data){
        lillyLivered = [];
        lillyLivered.push(new word(data.list[0].word, data.list[0].definition, data.list[0].example));
        console.log(lillyLivered);

        $('.container-fluid').html('<div class="row message unread">' + 
        ' <div class="col-xs-12 col-sm-6 col-lg-3 malok ' + color[i] + ' id="">' +
        '<div class="row dict">' + 
        '<div class="col-xs-9 col-sm-9 col-lg-9">' + 
        '<h3 class="term term0">' +
        lillyLivered[i].term + 
        '</div><div class="col-xs-3 col-sm-3 col-lg-3">' +
        '<div class="col-xs-3 col-sm-3 col-lg-3">' + 
        ' <span class="step size-32"><i class="icon ion-ios7-world"></i></span>' +
        '</div></div>' + 
        '<div class="row dict"><div class="col-xs-12 col-sm-12 col-lg-12">' +
        '<p class="definition definition0">' + 
        lillyLivered[i].def +
        '</p><p class="eg eg0">' + 
        lillyLivered[i].example + 
        '</p></div></div></div>'
        );
    }
)};

我这里有一个问题:http://jsfiddle.net/orenthal/5X96B/

如果我使用lillyLivered[0],这段代码会起作用。如果我使用lillyLivered[i],它根本不会加载。我收到以下错误:

Uncaught TypeError: Cannot read property 'term' of undefined (anonymous function)

我对此感到困惑。 lillyLivered 的控制台输出仅显示 lillyLivered 数组中索引位置 2 处的项目。在这种情况下,“你听到了”:

lillyLivered
[ word
    def: "Do you understand me? [ya heard] popular in New Orleans. the phrase is suppose to come after a sentence."
    example: "Say brah, I'm chillin here in Orlando, ya heard me. ↵-C-murder's innocent, ya heard me."
    term: "ya heard me"

我认为问题的存在可能是因为对lillyLivered[i].term 等的调用包含在与对 JSON 数据的调用相同的 for 循环中?所以我试着用两个循环来做这个。

我创建了一个新的 for 循环,该循环将负责创建 div 并从 lillyLivered 数组中输出项目,但我在这里遇到了同样的问题。

Uncaught TypeError: Cannot read property 'term' of undefined 

但这有助于解决其中一个问题,即lillyLivered 的控制台输出现在列出了词典中的所有四个单词及其定义和示例。

lillyLivered
[word, word, word, word]

我这里有一个小提琴: http://jsfiddle.net/orenthal/5bTrJ/

我觉得我在这里很密集并且遗漏了一些非常明显的东西。

【问题讨论】:

  • 这是一个常见问题——但如果您不知道神奇的词,搜索起来会非常棘手。

标签: javascript json for-loop


【解决方案1】:

是的,您的问题与闭包有关。您的 get 请求很可能在所有请求都已发送很久之后完成(并调用它们各自的回调)。因此,在调用回调时,i 将等于 lexicon.length。您可以通过将 get 请求包含在其自己的功能范围内并将当时的索引 i 传递到该范围内来解决此问题。像这样:

for (var i = 0; i < lexicon.length; i++) {
    (function(i) {
        $.getJSON('http://api.urbandictionary.com/v0/define?term=' + lexicon[i],
            function(data){
                lillyLivered = [];
                lillyLivered.push(new word(data.list[0].word, data.list[0].definition, data.list[0].example));
                console.log(lillyLivered);

                $('.container-fluid').html('<div class="row message unread">' + 
                ' <div class="col-xs-12 col-sm-6 col-lg-3 malok ' + color[i] + ' id="">' +
                '<div class="row dict">' + 
                '<div class="col-xs-9 col-sm-9 col-lg-9">' + 
                '<h3 class="term term0">' +
                lillyLivered[i].term + 
                '</div><div class="col-xs-3 col-sm-3 col-lg-3">' +
                '<div class="col-xs-3 col-sm-3 col-lg-3">' + 
                ' <span class="step size-32"><i class="icon ion-ios7-world"></i></span>' +
                '</div></div>' + 
                '<div class="row dict"><div class="col-xs-12 col-sm-12 col-lg-12">' +
                '<p class="definition definition0">' + 
                lillyLivered[i].def +
                '</p><p class="eg eg0">' + 
                lillyLivered[i].example + 
                '</p></div></div></div>'
                );
            }
        )};
    }(i));
}

另一个答案也提到了关于lillyLivered的一个好点。

编辑: 由于需求量大 :D,您还可以使用 forEach 方法来清理您的代码并解决您的问题:

lexicon.forEach(function(lexItem, i){
            $.getJSON('http://api.urbandictionary.com/v0/define?term=' + lexItem, // lexItem === lexicon[i]
                function(data){
                    lillyLivered = [];
                    lillyLivered.push(new word(data.list[0].word, data.list[0].definition, data.list[0].example));
                    console.log(lillyLivered);

                    $('.container-fluid').html('<div class="row message unread">' + 
                    ' <div class="col-xs-12 col-sm-6 col-lg-3 malok ' + color[i] + ' id="">' +
                    '<div class="row dict">' + 
                    '<div class="col-xs-9 col-sm-9 col-lg-9">' + 
                    '<h3 class="term term0">' +
                    lillyLivered[i].term + 
                    '</div><div class="col-xs-3 col-sm-3 col-lg-3">' +
                    '<div class="col-xs-3 col-sm-3 col-lg-3">' + 
                    ' <span class="step size-32"><i class="icon ion-ios7-world"></i></span>' +
                    '</div></div>' + 
                    '<div class="row dict"><div class="col-xs-12 col-sm-12 col-lg-12">' +
                    '<p class="definition definition0">' + 
                    lillyLivered[i].def +
                    '</p><p class="eg eg0">' + 
                    lillyLivered[i].example + 
                    '</p></div></div></div>'
                    );
                }
            )};
});

【讨论】:

  • +1,而不是一个立即调用匿名函数的循环,为什么不使用 Array.forEach 代替呢?所以...lexicon.forEach(function(item,i){dosomething();})?更少的大括号和支架,更容易在眼睛上,更不容易出现错误。 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
  • @spender — 请注意,“匿名函数”是 function expression 的行话。只是让你知道。 :-)
  • @spender 我认为匿名函数使答案更加清晰。 forEach 更简洁,可能是更好的解决方案,但我认为它不会更容易理解原始代码的问题。
  • 谢谢@RobG。 SO继续教育! Javascript 不是我的出生语言 :-)
  • @SimpleJ:在我看来,(糟糕地)跟踪索引会导致许多错误,但同意 Array.forEach 对学习者来说可能更加不透明。
【解决方案2】:

每次调用 getJson 时,您都在重新定义 lillyLivered,因此不会有 ith 术语。改变这个:

for (var i = 0; i < lexicon.length; i++) {

$.getJSON('http://api.urbandictionary.com/v0/define?term=' + lexicon[i],
    function(data){
        lillyLivered = [];

收件人:

var lillyLivered = [];
for (var i = 0; i < lexicon.length; i++) {

    $.getJSON('http://api.urbandictionary.com/v0/define?term=' + lexicon[i],
        function(data){...}
}

【讨论】:

  • 感谢您的浏览。在第二轮中,我确实将列表数组移出 for 循环,这会导致正确创建列表。 jsfiddle.net/orenthal/5bTrJ 在此迭代中,我在从列表中获取信息以显示时遇到问题。我会继续玩弄它的。再次感谢!
【解决方案3】:

如果我正确阅读了您的问题,您希望一次在页面上显示所有结果,而您只看到最后一个?

如果这是问题所在,那么问题是每次从 api 获取新项目时都会覆盖 div。如果您更改使用 .html 将 html 写入 dom 的代码:

$('.container-fluid').html(...);

改为使用 .append,您将在页面上看到所有结果:

$('.container-fluid').append(...);

【讨论】:

  • 这对我的 div 输出帮助很大。我仍然对列表有疑问,但我已经获得了我应该阅读的文档的链接。谢谢@intelligentbean。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-31
  • 1970-01-01
  • 1970-01-01
  • 2015-06-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多