Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/actionscript-3/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flash 在循环中创建函数(指针?)_Flash_Actionscript 3_Actionscript_Flash Cs4 - Fatal编程技术网

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

Flash 在循环中创建函数(指针?),flash,actionscript-3,actionscript,flash-cs4,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:

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


非常感谢。

这是一个AS3缺陷,来自废弃的ECMA脚本草案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));

附带说明:没有此缺陷。

我看到答案已被选中,但我不同意该解决方案,尽管它确实有效。我不会将此描述为AS3的缺陷,因为这与同样基于ECMAScript的Javascript的情况相同。在任何情况下,只要为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);
}

我同意wpjmurray的观点,这根本不是一个缺陷;相反,这是EcmaScript中作用域工作方式的结果

单击处理程序包含对变量n的隐式引用。当通过单击触发调用函数时,该变量的值已更改。当你这样想的时候,它是非常有意义的

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

创建一个新闭包,该闭包本身具有对另一个变量的隐式引用,该变量的值设置一次,然后保持不变。back2dos的解决方案是这样做的一种方法:makeFunction创建一个新的方法闭包,该闭包包含对新变量makeFunction的n参数的隐式引用,该参数不变。 将该值存储为对象上的属性。这是wpjmurray建议的,但您无法做到。 将值存储在地图中并进行查找。您在提到将X/Y坐标映射到索引时暗示了这一点。然而,ActionScript3提供了一个更加优雅的解决方案:解决方案!只需将对象本身映射到索引,然后在处理程序中查找它。 下面是一个例子:

var dict:Dictionary = new Dictionary(true);
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);
        dict[btt] = n;
        btt.addEventListener(MouseEvent.CLICK, function f(event:MouseEvent) { trace(dict[event.currentTarget]); } );
    }
}

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

BasicGameButton不是一个类,而是flash库中SimpleButton的一个实例,我希望避免专门为它创建一个类。因此,btt.n=n不起作用,除非有一种从外部创建新变量的方法。另外,我使用的实际代码比我上面发布的代码稍微复杂一些,所以我不能在父级上真正使用eventListener,因为在后台会有多个按钮等等。不过,我很感谢你的意见。