为何ActionScript 3.0简单程序会出现如此意外的输出?
为什么你的ActionScript 3.0程序输出出乎意料?
嘿,这个坑我当初刚学AS3的时候也踩过!先还原你截图里的核心代码(避免外链,直接贴出):
var i:int; for(i = 0; i < 5; i++){ setTimeout(function():void{ trace("Count: " + i); }, 100); }
你原本应该以为会依次输出Count: 0到Count: 4,但实际却输出了5次Count: 5,对吧?
问题根源:闭包对变量的引用捕获
在AS3里,setTimeout里的匿名函数(也就是闭包)并不会捕获变量i的当前值,而是捕获了变量i的内存引用。
因为setTimeout是异步执行的——循环会先一口气跑完,这时候i已经被递增到5了;等过了100毫秒,这5个匿名函数才依次执行,它们读取的都是同一个i变量的当前值,自然全都是5。
解决办法
要解决这个问题,你需要给每个异步函数创建独立的变量作用域,把当前的i值“固定”下来,这里有两种常用方法:
方法1:使用立即执行函数(IIFE)
var i:int; for(i = 0; i < 5; i++){ // 用立即执行函数创建独立作用域,保存当前i的值 (function(currentI:int):void{ setTimeout(function():void{ trace("Count: " + currentI); }, 100); })(i); }
这里我们通过立即执行函数,把每次循环的i值作为参数传递进去,这样每个闭包捕获的都是独立的currentI变量,它的值就是循环时的当前值。
方法2:使用Function.bind()(AS3.0及以上版本支持)
var i:int; for(i = 0; i < 5; i++){ // 用bind绑定当前i值作为函数参数 setTimeout(function(currentI:int):void{ trace("Count: " + currentI); }.bind(null, i), 100); }
bind()方法会创建一个新的函数,把我们传入的i值绑定为函数的参数,这样每个异步函数执行时都会拿到对应的固定值。
如果你的程序是其他数值相关的出乎意料输出(比如整数溢出),可以补充代码细节再讨论,但根据你提供的截图内容,这个闭包引用的问题是最可能的原因~
内容的提问来源于stack exchange,提问作者Potato23
相关产品推荐
相关产品推荐

