如何解决ActionScript 3(AS3)中的闭包问题

fro*_*ega 25 apache-flex flash closures actionscript-3

在下面的代码中,我试图加载一些图像,并在它们单独加载后立即将它们放入舞台.但它被窃听,因为只显示最后一张图像.我怀疑这是一个关闭问题.我该如何解决?AS3中的闭包行为与Java Script中的行为不一样吗?

var imageList:Array = new Array();
imageList.push({'src':'image1.jpg'});
imageList.push({'src':'image2.jpg'});
var imagePanel:MovieClip = new MovieClip();
this.addChildAt(imagePanel, 0);

for (var i in imageList) {
    var imageData = imageList[i];
    imageData.loader = new Loader();

    imageData.loader.contentLoaderInfo.addEventListener(
        Event.COMPLETE, 
        function() {
            imagePanel.addChild(imageData.loader.content as Bitmap);
            trace('Completed: ' + imageData.src);             
        });

    trace('Starting: ' + imageData.src);
    imageData.loader.load(new URLRequest(imageData.src));   
}
Run Code Online (Sandbox Code Playgroud)

bob*_*nce 45

AS3中的闭包行为与Java Script中的行为不一样吗?

是的,JavaScript完全一样.和Python一样.和别的.

虽然在'for'中定义'var imageData',但for循环不会在这些语言中引入新的范围; 事实上,变量imageData绑定在包含范围内(外部函数,或者在这种情况下,它似乎是全局范围).您可以在循环完成执行后查看imageData并在其中查找imageList的最后一个元素来验证这一点.

因此,只有一个imageData变量,而不是循环的每次迭代都有一个变量.当COMPLETE触发时,它进入闭包并读取imageData 现在具有的任何值,而不是在定义函数时(*).通常,for循环将通过COMPLETE点完成,而imageData将保留最后一次迭代中的最后一个元素.

(* - 存在'早期绑定'语言,它将在您定义闭包时评估变量的值.但ActionScript不是其中之一.)

可能的解决方案往往涉及使用外部函数来引入新范围.例如:

function makeCallback(imageData) { return function() {
    imagePanel.addChild(imageData.loader.content as Bitmap);
    trace('Completed: ' + imageData.src);                                                                                                     
} }
...
imageData.loader.contentLoaderInfo.addEventListener(Event.COMPLETE, makeCallback(imageData));
Run Code Online (Sandbox Code Playgroud)

你/可以/把这个内联,但双重嵌套的函数()开始变得难以阅读.

另请参见Function.bind()以获取可用于实现此功能的通用部分函数应用程序功能.它可能是未来JavaScript/ActionScript版本的一部分,并且可以在此期间通过原型设计添加到语言中.

  • 本质上不是,不是,但jQuery的sequence.Each()在每次迭代时调用一个函数,每次都重新绑定函数变量.因此,它避免了for/while循环可能遭受的问题. (2认同)