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()
输出来判断。 states
或key
绝对没有问题,它完美地遍历字典中的每个状态。即使API调用也是正确的。但是,#missing-states-list
附加的内容始终为Wyoming
,这是abvMap
中的最后一项。我知道为什么。
答案 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
循环导致正在打印9
到10
,但您会获得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
创建for
,i
循环的每次迭代都有其“自己的”变量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解决方案,一个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中){ ...
}