as学习笔记(二一)--as3的变量作用域与生命周期
sshong 发表于2008年7月7日 11:19:00 更新于2008年7月24日 11:23:00
在任何一门编程语言中,变量作用域和生命周期都是两个十分重要的话题

在c++中,变量作用域与生命周期相关的重要概念有堆、栈、静态数据区等,而在java以及as3中,由于是由虚拟机来完成内存的分配以及释放,因此对于c++编程人员来说,一方面可能以为以前调试时一大堆memory leak的问题不会存在,一方面可能又害怕java以及as3的gc(garbage collector)有没有c中手工的delete管用。

的确,gc并不是万能,我很头疼,从前几篇文章中可以看出gc的不足之处,因为出现bug后,c++编程人员知道肯定是new了没有delete,慢慢查或者借助相关工具如bounds checker等总是可以解决的,而在as3中可能会有些昏头转向。

转入正题

c++中变量作用域与as3中类似,除了as3中有一个hoisting机制会将某函数内部声明的所有局部变量全部提升到最开始,因此,如果在函数内部有两个for,在c中可以for(int i=0;;){} for(int i=0;;){},而在as3中如果for(var i:int=0;;){} for(var i:int=0;;){},则会报Warning: 3596: 变量定义重复,一开始我是被蒙了好多回

c++的变量生命周期跟变量存放位置有关,在栈上,则出栈即可视为被清空(实质等下一次覆盖这块内存区域);在堆上,则直道显示delete才可视为清空。

而as3中没有堆栈的概念,我们姑且认为所有的变量内存都统一放到某处,只不过各个变量有不同的作用域,那么到底什么时候变量对应的内存区域被清空呢?这就是gc老大人的责任了,gc老大人的怪脾气以及工作机制在as3中的资源管理与GC中有描述,一旦gc根据其运行机制认为某变量可以被清空,即清空之。

一个很重要的问题是,对于c++编程人员,可能以为在函数内部定义的“栈”上局部变量,出这个函数这个变量就会被清空!错,千万不能用这种思维,

搞的不好这个局部变量对应的内存将一直存在!!
譬如
function cFTas():void
{
    var tmp:loader = new URLLoader(new URLRequest("http://www.asarea.me"));
    tmp.addEventListener(ProgressEvent.PROGRESS, onloading);)
}
如果是按照c++的思维方式,tmp出cFTas就该喀了,那么tmp的事件监听就无从说起了。

我的理解,变量在离开作用域时,仅仅相当把该变量对应的内存空间的引用减少了1个

那么是谁对tmp有引用呢?谁妨碍了gc对tmp的清理呢?

一种可能是as内部的事件流机制有关,对于内部定义的一些事件,它的dispatch是何时何地怎么触发的都不得而知,肯定这个机制里面为了保证某些事件能够正确触发保留了对tmp的引用!

ps:奇怪的是,除了loader之类的流加载相关,如果是其他事件,居然出了这个函数,遇到下一个gc就会清空tmp,真是搞不懂啊,测试例子,感谢gene,单击stage会发现enterframe消失了,而loading和complete依然存在!

08.7.24加:奇怪,今天发现filereference如果定义在某个函数内部,然后在函数内部对它加各种事件,发现根本不起作用,说明这个fr出了这个函数就被喀掉了!如果把fr声明在外(也就是在外部有一个引用),而在函数内部new,结果又是可以的!而loader之类的之所以可以在函数内部定义,说明跟flash自身机制有关,在别处有对loader的引用了!

package
{
    import flash.net.*;
    import flash.display.Sprite;
    import flash.events.*;

    public class test extends Sprite
    {
        public function test()
        {
            var tmp:Sprite = new Sprite();
            tmp.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
            stage.addEventListener(MouseEvent.CLICK, gc);
            var tmp2:URLLoader = new URLLoader(new URLRequest("http://www.yzsxwj.cn/molihua.rm"));
            tmp2.addEventListener(ProgressEvent.PROGRESS, onloading);
            tmp2.addEventListener(Event.COMPLETE, oncomplete);
        }
        private function enterFrameHandler(evt:Event):void
        {
            trace("enterframe");
        }
        private function oncomplete(event:Event):void
        {
            trace("completed");
        }
        private function onloading(evt:ProgressEvent):void
        {
            trace("onloading");
            trace(evt.target);//.close();
        }
        private function gc(event:Event):void
        {
            try
            {
                new LocalConnection().connect("gc");
                new LocalConnection().connect("gc");
            }
            catch (error:Error)
            {
            }
        }
    }
}
标签:as3c++作用域生命周期分类:As3&Flex阅读:6442
评论
sshong2013年2月19日 23:43
整理博客,回答下,所有异步加载的事件都是如此,参考上一篇博客关于removelistener的回复。
shavy2008年12月24日 11:08
AS3的内存泄漏问题真的是很烦。。。。
添加评论
您的大名,限长10汉字,20英文(*)
电子信箱(*)
您的网站
正文,限长500汉字,1000英文(*)
验证码(*) 单击刷新验证码
联系我
博客订阅