为什么我只从javascript循环中获取最后一项?

时间:2014-05-08 20:27:29

标签: javascript json for-loop

我已经尝试过搜索这个问题,并且已经找到了一些问题,这些问题来自人们的for循环问题并且只返回最后一个元素。尽我所能,我只是不明白我在这里做错了什么。

我对Javascript很陌生,所以我觉得我有关闭的问题?我写的东西应该从Urbandictionary API返回的JSON中获取一些数据。 JSON提取有效但我的 for 循环用于构建具有该数据的div无法正常工作。

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处的项目。在这种情况下&#34;你听到我&#34;:

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循环,它将负责创建div并从lillyLivered数组中输出项目,但我在这里遇到了同样的问题。

Uncaught TypeError: Cannot read property 'term' of undefined 

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

lillyLivered
[word, word, word, word]

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

我感觉自己很紧张,在这里发现了一些非常明显的东西。

3 个答案:

答案 0 :(得分:2)

是的,您的问题与闭包有关。在发送完所有请求后很长时间内,您的获取请求可能会完成(并调用各自的回调)。因此,在调用回调时,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 :(得分:1)

每次致电lillyLivered时,您都会重新定义getJson,因此不会成为i个字词。改变这个:

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){...}
}

答案 2 :(得分:1)

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

如果这是问题,那么问题是每次从api获得新项目时都要覆盖div。如果你改变你的代码,用html写html到dom:

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

使用.append而不是您将在页面上看到所有结果:

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