JQuery没有将正确的值附加到无序列表

时间:2018-02-23 23:38:15

标签: javascript jquery

function endGame(num) {
    var total = Object.keys(abvMap).length;

    $("#result").empty();

    if(num == total) {
        // you won
        $("#result").append("<h4>YOU WON!</h4><p>You got all " + total + " states!</p>");
    } else {
        console.log(states);
        // didn't get all 51 states
        $("#result").append("<h4>ALMOST!</h4><p>You got " + num + " out of " + total +" states!</p><h3>Missing states:</h3><ul id=\"missing-states-list\"></ul>");
        for(var key in abvMap) {
            if(($.inArray(key, states)) == -1) {
                console.log(key);
                $.get("https://api.census.gov/data/2013/language?get=EST,LANLABEL,NAME&for=state:" + abvMap[key] + "&LAN=625", function(data) {
                    $("#missing-states-list").append("<li><div class=\"tooltip\">" + key + "<span class=\"tooltiptext\">" + data[1][0] + " spanish speakers</span></div></li>");
                });
            }
        }
    }
}

此文件的详细信息无关紧要。这里的问题是在for循环中,字典key中的每个abvMap都在循环中。 states是一个全局数组,包含已经找到的状态,例如states = ["Maryland", "Texas"]abvMap是一个包含所有51个州的字典。我正在检查已经找到key状态的for循环的每次迭代。如果没有,我进行API调用并将该状态(以及API中的一些数据)附加到列表#missing-states-list

根据console.log()输出来判断。 stateskey绝对没有问题,它完美地遍历字典中的每个状态。即使API调用也是正确的。但是,#missing-states-list附加的内容始终为Wyoming,这是abvMap中的最后一项。我知道为什么。

3 个答案:

答案 0 :(得分:2)

问题的原因:缺乏理解var

选中此示例以了解问题:

function scope创建var funcs = [] for (var i = 0; i < 10; i++) { funcs.push(function() { console.log(i) }) } funcs.forEach(function(func) { func() })

forEach

虽然您可能希望此0循环导致正在打印910,但您会获得10次i。造成这种情况的原因是使用var关键字声明变量function scope,这会创建function,导致funcs中的每个i持有引用相同的 forEach变量。在执行for循环时,先前的i - 循环已结束且let保持10(从上次迭代开始的9 ++)。

比较创建block scope而不是function scope的ES6 let在这方面的行为:

block scope(ES6或正式 ES2015 )创建var funcs = [] for (let i = 0; i < 10; i++) { funcs.push(function() { console.log(i) }) } funcs.forEach(function(func) { func() })

let

由于block scope创建fori循环的每次迭代都有其“自己的”变量IIFE

使用var funcs = [] for (var i = 0; i < 10; i++) { funcs.push((function(value) { return function() { console.log(value) } }(i))) } funcs.forEach(function(func) { func() })包装器

的ES5解决方案

如果你需要一个ES5解决方案,一个IIFE( i 立即 i nvoked f unction e xpression)包装将是要走的路:

i

此处,value作为参数传递给存储其自己的副本for..in的每个函数。

var funcs = [], obj = { first: "first", last: "last", always: "always" } for (var key in obj) { funcs.push(function() { console.log(key) }) } funcs.forEach(function(func) { // outputs: "always", "always", "always" func() })循环也是如此:

funcs

同样,reference中的所有函数都将key保持为相同的var key,因为for..in创建了一个位于let循环之外的函数作用域。同样,var funcs = [], obj = { first: "first", last: "last", always: "always" } for (let key in obj) { funcs.push(function() { console.log(key) }) } funcs.forEach(function(func) { func() })会产生您可能更期望的结果:

df2.groupby([df.DATE.dt.month,'NAME']).mean()

还要比较优秀的(!)书

  

Nicholas C. Zakas: "Understanding ES6",没有淀粉压榨,p。 8-9。

从中获取了这些例子。

答案 1 :(得分:1)

这是因为$.get是异步的,当它返回时,键总是在abvMap循环的末尾。

您需要围绕$.get来电创建一个人工关闭,以便保持key值(在调用时更正)。

(function (keysafe) {
    $.get("https://api.census.gov/data/2013/language?get=EST,LANLABEL,NAME&for=state:" + abvMap[keysafe] + "&LAN=625", function(data) {
    $("#missing-states-list").append("<li><div class=\"tooltip\">" + keysafe + "<span class=\"tooltiptext\">" + data[1][0] + " spanish speakers</span></div></li>");
    });
}(key));

答案 2 :(得分:1)

有时使用“var”只会显示列表中的最后一项。要保留每个项目/元素,您需要使用“let”,以便它可以重新绑定到每次迭代(ES6)。

如何在for循环中将“var”切换为“let”?

  

for(键在abvMap中){    ...
  }