javascript 在引用外部作用域变量的循环中声明的函数可能会导致语义混淆。怎么了?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/46027262/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Functions declared within loops referencing an outer scoped variable may lead to confusing semantics. What is wrong?
提问by Emilio
Can someone tell me what is wrong with my code, especially the "Full screen event" part. Thanks!
有人可以告诉我我的代码有什么问题,尤其是“全屏事件”部分。谢谢!
JSLint says "Functions declared within loops referencing an outer scoped variable may lead to confusing semantics."
JSLint 说“在引用外部作用域变量的循环中声明的函数可能会导致语义混乱。”
function initialize() {
var mapProp = {
center: new google.maps.LatLng(45.502808, -73.571486),
};
var map = [];
map[0] = new google.maps.Map(document.getElementById("map1"), mapProp);
map[1] = new google.maps.Map(document.getElementById("map2"), mapProp);
map[2] = new google.maps.Map(document.getElementById("map3"), mapProp);
new google.maps.Marker({
position: new google.maps.LatLng(45.502808, -73.571486),
map: map[0], title: 'Sunnyvale '
});
new google.maps.Marker({
position: new google.maps.LatLng(45.502808, -73.571486),
map: map[1], title: 'Sunnyvale '
});
new google.maps.Marker({
position: new google.maps.LatLng(45.502808, -73.571486),
map: map[2], title: 'Sunnyvale '
});
google.maps.event.addDomListener(window, "resize", function () {
for (i = 0; i < 3; i++) {
var center = map[i].getCenter();
/*var bounds = map[i].getBounds();*/
var zoom = map[i].getZoom();
google.maps.event.trigger(map[i], "resize");
/*map[i].fitBounds(bounds);*/
map[i].setCenter(center);
google.maps.event.addListenerOnce(map[i], 'bounds_changed', function(event) {
this.setZoom(zoom);
});
}
});
/** Full Screen event */
for (i = 0; i < 3; i++) {
var centerChanged = [];
var zoomChanged = [];
google.maps.event.addListener(map[i], 'center_changed', function() {
var centerChanged[i] = map[i].getCenter();
var zoomChanged[i] = map[i].getZoom();
});
$(document).on('webkitfullscreenchange mozfullscreenchange fullscreenchange', function() {
map[i].setCenter(centerChanged[i]);
google.maps.event.addListenerOnce(map[i], 'bounds_changed', function (event) {
this.setZoom(zoomChanged[i]);
});
});
}
}
google.maps.event.addDomListener(window, 'load', initialize);
JSLint says "Functions declared within loops referencing an outer scoped variable may lead to confusing semantics."
JSLint 说“在引用外部作用域变量的循环中声明的函数可能会导致语义混乱。”
回答by EKW
In your loop, i starts at 0 and iterates until it's equal to 3. That means that whenever you access i after the loop has finished running (for example, in a listener function) it will be equal to 3. You can see this in the following code:
在您的循环中,我从 0 开始并迭代直到它等于 3。这意味着每当您在循环完成运行后访问 i(例如,在侦听器函数中)它将等于 3。您可以在以下代码:
for(var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
That will print all 5s because the function is being called after the loop has finished iterating.
这将打印所有 5,因为该函数在循环完成迭代后被调用。
Edit: To fix the issue, you can use javascript's hip new declaration statements: let and const. They exist only in the scope that they are declared, and their values are therefore not overwritten.
编辑:要解决此问题,您可以使用 javascript 的新声明语句:let 和 const。它们只存在于它们被声明的范围内,因此它们的值不会被覆盖。
for(var i = 0; i < 5; i++) {
const j = i;
setTimeout(function() {
console.log(j);
}, 1000);
}
Edit 2: Replacing var iwith let iappears to work as well:
编辑2:更换var i同let i似乎工作,以及:
for(let i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
Edit 3: If es6 isn't an option, you could bind i's value to the function:
编辑 3:如果 es6 不是一个选项,您可以将 i 的值绑定到函数:
for(var i = 0; i < 5; i++) {
setTimeout((function(j) {
console.log(j);
}).bind(null, i), 1000);
}
回答by Jorge Valle
In your loop, you are not declaring the ivariable with var, thereby implicitly creating this variable in the global scope.
在您的循环中,您没有使用 声明i变量var,从而在全局范围内隐式创建此变量。

