有人可能会指出为什么以下代码在第一种情况下失败:
案例1
// In a constructor
this.gallery = new Gallery();
addChild(this.gallery);
this.gallery.addEventListener(GalleryEvent.WHATEVER, function(event:*) {
// When this callback fires, there is a fail:
// because there is no 'this.gallery'.
this.gallery.someAction();
});
案例2
this.gallery.addEventListener(GalleryEvent.WHATEVER, function(event:*) {
// This works fine
gallery.someAction();
})
在这种情况下是否有关于this
使用的规则?
答案 0 :(得分:6)
这是因为“范围链”。在ActionScript 3(符合ECMAScript - JavaScript具有下面描述的相同行为)中,有一个内置的“places”列表,用于解析任何名为变量的命名变量。例如。当在类的“正常”方法中时,范围链看起来像这样:
this
相同)Math
)但是当你在匿名内部函数中时,作用域链在顶部还有一个条目,表示在匿名函数创建时的范围内的方法 。例如,假设您有以下代码:
class C {
var membervar:int;
function f() {
var localvar:int;
var innerfunc:Function = function() {
// what is on the scopechain here?
};
innerfunc();
}
}
在这种情况下,如果你是“这里scopechain上有什么”的行,那么scopechain就是这样(下面的第一个范围是第一个要检查的范围):
f()
的一个实例,包含变量localvar
和innerfunc
C
C
重要的是要意识到,当代码行var innerfunc:Function = function()...
执行时,它会动态创建Function对象,并动态设置其范围链。例如,假设你有这个(令人困惑的)代码,给定一个参数an_arg
,它返回一个Function,当被调用时,它将打印an_arg的值:
function f(an_arg:int):Function {
return function():void {
trace(an_arg);
}
}
调用f()
返回的每个函数都有自己的作用域链,指向f()
的不同实例。所以:
var func1:Function = f(3);
var func2:Function = f(4);
func1(); // prints 3
func2(); // prints 4
如果你真的想在内部函数中引用this
而不是依赖于范围链的魔力,那么避免这个问题的常用方法是创建一个名为self
的临时变量在外部函数中 - 在示例代码的情况下,它看起来像这样:
var self = this;
this.gallery.addEventListener(GalleryEvent.WHATEVER, function(event:*) {
// This works fine
self.gallery.someAction();
})
我可以永远继续这个主题 - 我发现它很有趣: - )
答案 1 :(得分:4)
因为你传递了这个函数function(event:*)
,这意味着它在那个范围内执行。
所以当它试图寻找this
时,它正在寻找event.gallery.someAction();
当您使用gallery
时,它会尝试在全局变量列表中找到它。
验证这一点的一种方法是添加一个跟踪(这个),看看会发生什么。