在循环中创建一个函数(指针?)

时间:2010-05-27 16:06:02

标签: flash actionscript-3 actionscript flash-cs4

我试图创建一个简单的循环,创建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库中创建)

非常感谢。

3 个答案:

答案 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)的隐式引用。调用该函数(通过单击触发)时,该变量的值已更改。当你以这种方式思考时,这是非常有意义的。

解决方案是将值存储在每次迭代中,并以某种方式将其与您的按钮相关联。有三种好方法可以做到这一点:

  1. 创建一个新的闭包,它本身具有对另一个变量的隐式引用,该变量的值设置一次然后单独保留。 back2dos的解决方案是一种方法:makeFunction创建一个新的方法闭包,它隐含引用 new 变量(makeFunction的{​​{1}}参数)这不会改变。
  2. 将值存储为对象的属性。 (这是wpjmurray提出的,但你无法做到。)
  3. 将值存储在地图中并查找。当您提到将X / Y坐标映射到索引时,您暗示了这一点。但是,ActionScript 3提供了更多......优雅(:解决方案:Dictionary class!只需将对象本身映射到索引,然后在处理程序中查找。
  4. 以下是一个例子:

    n

    由于范围在EcmaScript中的工作方式,您创建的每个单击处理程序都带有对字典的隐式引用,您可以使用它来查找索引。现在,索引直接映射到按钮,无需添加属性或创建新函数。