我试图创建一个简单的循环,创建50个按钮,将它们添加到屏幕,然后当按下按钮时,它会追踪该数字。我可以通过做我认为hacky的东西(例如使用按钮X / Y位置来确定它的值)让它工作,但我宁愿只能在函数中保存一个值。
代码本身是:
for (var a:int = 0; a < 5; a++) {
for (var b:int = 0; b < 10; b++) {
var n = (a * 10) + b + 1;
var btt:SimpleButton = new BasicGameButton();
btt.x = 20 + b * 50;
btt.y = 50 + a * 80;
addChild(btt);
btt.addEventListener(MouseEvent.CLICK, function f() { trace(n); } );
}
}
此刻,只要按下按钮,它就会输出“50”。对于该函数,有没有一种方法可以在创建函数时“冻结”n的值? (BasicGameButton只是一个方形按钮,在flash库中创建)
非常感谢。
答案 0 :(得分:0)
这是一个AS3漏洞,来自废弃的ECMA-Script草案AS3基于...... n
的范围是它所声明的最里面的函数体(因此好像它是在循环之前声明的) ,虽然在代码的最里面的循环体中声明。
您可以执行以下操作:
var makeFunction:Function = function (n:int):Function {//this can of course also be a method
return function (event:MouseEvent):void {
trace(n);
}
}
//in the loop body, use it like this:
btt.addEventListener(MouseEvent.CLICK, makeFunction(n));
作为旁注:Haxe没有这个缺陷。
答案 1 :(得分:0)
我看到答案已被选中,但我不同意该解决方案,尽管它确实有效。我不认为这是AS3的一个缺陷,因为这种情况与Javascript相同,也基于ECMAScript。在任何情况下,只需为BasicGameButton创建一个包含n值的属性,就可以完全避免这个问题。此外,不是为每个按钮添加一个侦听器,只需在按钮容器上创建一个侦听器,该侦听器侦听鼠标单击(鼠标单击“气泡”直到父显示对象)并使用事件目标获取单击的按钮。
/* inside the loop */
btt.n = n;
/* parent listener you only have to create once */
buttonContainer.addEventListener(MouseEvent.CLICK, onClick);
function onClick(e:Event):void {
trace(BasicGameButton(e.target).n);
}
答案 2 :(得分:0)
我同意wpjmurray的说法,这根本不是一个缺陷;相反,它是范围在EcmaScript中如何工作的结果。
您的点击处理程序带有对变量(n
)的隐式引用。调用该函数(通过单击触发)时,该变量的值已更改。当你以这种方式思考时,这是非常有意义的。
解决方案是将值存储在每次迭代中,并以某种方式将其与您的按钮相关联。有三种好方法可以做到这一点:
makeFunction
创建一个新的方法闭包,它隐含引用 new 变量(makeFunction
的{{1}}参数)这不会改变。以下是一个例子:
n
由于范围在EcmaScript中的工作方式,您创建的每个单击处理程序都带有对字典的隐式引用,您可以使用它来查找索引。现在,索引直接映射到按钮,无需添加属性或创建新函数。