public var func:Function = null;
public function Test()
{
func = func1;
addEventListener(Event.ENTER_FRAME, func);
removeEventListener(Event.ENTER_FRAME, func);
func = func2;
addEventListener(Event.ENTER_FRAME, func);
}
public function func1(e:Event):void
{
trace("this is wrong");
}
public function func2(e:Event):void
{
trace("this is right");
}
声明回调函数,并把它注册到特定的事件上,由事件触发这个函数的调用,是as3中常用的手法。有一个问题,可能很少有人遇到过,那就是:
当你声明一个函数变量 var func:Function;然后将其赋值为某个已知函数func1(), 然后把它注册起来,比如最常见的:
addEventListener(Event.ENTER_FRAME, func);
此时,你再改变func: func = func2();
请问此时, 每次ENTER_FRAME时,执行的是 func1() 还是 func2() ?
经过测试,结果仍然是func1(), 如果你要让他改成调用func2, 必须先remove掉对 func 的监听, 然后对其赋值, 令 func = func2,
再把func重新注册,才能成功的改回调函数为func2。
其实这很符合程序语言的基本思想,当让func引用func1时,此时注册他,注册的是func1这个对象,注册完毕之后,再给func赋值为func2,只是改变了func引用的对象,并没有实际改变注册在ENTER_FRAME上的回调函数,所以简单的改变func的指向,是无法影响已经注册的回调函数的。
但我要达到这种目的该怎么做呢?
public var func:Function = null;
public function Test()
{
func = func1;
addEventListener(Event.ENTER_FRAME, funX);
func = func2;
}
public function funX(e:Event):void
{
trace("funX called");
func(e);
}
public function func1(e:Event):void
{
trace("this is wrong");
}
public function func2(e:Event):void
{
trace("this is right");
}
这样就可以了,为什么这样就行得通? 因为通过让回调函数调用你的函数变量, 这样你在外部改变你的函数变量的指向,就是确确实实的改变了你注册的回调函数的行为,所以能够成功, 之前那种通过重新赋值来改变注册的回调函数“指针”的尝试,在这种高级语言里是不会成功的。