有人可以解释为什么下面的跟踪返回数组的长度而不是数组项中“i”的值吗?
非常感谢,尼克
AS3
function createMarkers(mapLocations){
var markerArray:Array = new Array();
for(i=0; i<mapLocations.length; i++){
markerArray.push(new marker());
markerArray[i].x=mapLocations[i][1];
markerArray[i].y=mapLocations[i][2];
markerArray[i].markerText.text = mapLocations[i][0].toString();
markerArray[i].addEventListener(MouseEvent.CLICK, function(e:MouseEvent){clickTarget(e,i);});
bgImage.addChild(markerArray[i]);
}
}
function clickTarget(e:MouseEvent,a){
trace(a);
}
最佳答案
这是处理 JavaScript/ActionScript 函数时的常见错误。您之所以遇到问题,是因为函数是闭包,这意味着它们在定义函数时保存对作用域中定义的变量的引用。
这意味着您的匿名处理函数关闭围绕i
变量,但它存储对其的引用,而不是其值。由于 i
发生变化,每个函数都保存对同一变量的引用,该变量仅保存分配给它的最后一个值。
基本上,如果您想要关闭变量的特定值,则必须在函数作用域内声明该变量(使用var
语句)。因此,这看起来应该可行:
for (var i:int = 0; i < 10; i++) {
var scopedI:int = i;
mc[i].addEventListener(MouseEvent.CLICK, function (e:MouseEvent) { trace(scopedI); });
}
我们在循环范围内声明一个新变量 scopedI
来专门关闭该值,因为该变量将在循环的每次迭代中使用唯一值重新声明。不幸的是,ActionScript 和 JavaScript 一样,没有 block 级作用域,只有函数级作用域,因此所有变量声明都“提升”到函数的顶部。
这几乎意味着您的 scopedI
类型与 i
以及该函数内声明的任何其他变量具有相同的作用域。那么,我们如何创建一个新的范围呢?具有更多功能。请记住,在 ActionScript 中,函数是对象,因此我们可以做如下疯狂的事情:
(function (id) {
return function () { trace(id); };
})(7);
这段代码创建了一个函数,然后立即使用 id
参数的值 7
执行该函数。这很有用,因为现在 id 的作用域是我们返回的内部函数,因此无论外部发生什么,该函数都将始终打印“7”。
同样,我们可以使用它来确定循环中的 i
变量的范围。您的代码可以更新为如下所示:
function createMarkers(mapLocations){
var markerArray:Array = new Array();
for(var i = 0; i < mapLocations.length; i++){
markerArray.push(new marker());
markerArray[i].x = mapLocations[i][1];
markerArray[i].y = mapLocations[i][2];
markerArray[i].markerText.text = mapLocations[i][0].toString();
markerArray[i].addEventListener(MouseEvent.CLICK, (function (scopedI) {
return function (e:MouseEvent) { clickTarget(e, scopedI); };
})(i));
bgImage.addChild(markerArray[i]);
}
}
function clickTarget(e:MouseEvent, a){
trace(a);
}
现在,scopedI
对于每次迭代都是唯一的。是的,语法有点困惑,但这最终成为该语言的一个极其强大和富有表现力的功能。如果你能理解它,它会非常有用。
关于actionscript-3 - Flash AS3函数跟踪相同的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14025783/