Actionscript 3'这个'问题

时间:2011-01-19 00:45:54

标签: flash actionscript-3 actionscript this

有人可能会指出为什么以下代码在第一种情况下失败:

案例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使用的规则?

2 个答案:

答案 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()的一个实例,包含变量localvarinnerfunc
  • 班级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时,它会尝试在全局变量列表中找到它。

验证这一点的一种方法是添加一个跟踪(这个),看看会发生什么。