【问题标题】:Actionscript 3 'this' questionActionscript 3“这个”问题
【发布时间】:2011-01-19 00:45:54
【问题描述】:

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

案例 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 的使用是否有任何规则?

【问题讨论】:

  • 尝试使用匿名函数不添加监听器。
  • @George 是的,它有效。我纯粹对为什么会发生这种情况感兴趣。
  • 已经有两个很好的答案,但是在 AS3 的上下文中阅读闭包也是值得的。

标签: flash actionscript-3 actionscript this


【解决方案1】:

这是因为“范围链”。在 ActionScript 3(它与 ECMAScript 兼容——JavaScript 具有下面描述的相同行为)中,有一个内置的“位置”列表,用于解析任何命名变量,称为作用域链。例如。在类的“普通”方法中,作用域链如下所示:

  • 当前实例对象(同this)
  • 类对象(用于访问静态变量)
  • 全局范围(用于访问全局变量,例如Math)

但是当你在一个匿名内部函数中时,作用域链的顶部多了一个条目,表示在匿名函数创建时作用域中的方法 .例如,假设您有以下代码:

class C {
    var membervar:int;

    function f() {
        var localvar:int;

        var innerfunc:Function = function() {
            // what is on the scopechain here?
        };

        innerfunc();
    }
}

在这种情况下,当您是“这里的作用域链上有什么”的那一行时,作用域链看起来像这样(下面的第一个作用域是要检查的第一个位置):

  • 函数f()的一个实例,带有变量localvar和innerfunc
  • 类C的当前实例
  • 班级C
  • 全球范围

重要的是要意识到,当代码行var innerfunc:Function = function()... 执行时,它正在动态创建Function 对象,并动态设置其范围链。例如,假设你有这个(令人困惑的)代码,给定一个参数an_arg,它返回一个函数,当被调用时,它将打印 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();
})

我可以在这个主题上永远继续下去——我觉得它很有趣:-)

【讨论】:

    【解决方案2】:

    因为你传递了这个函数function(event:*),这意味着它是在那个范围内执行的。

    所以当它试图寻找this 时,它正在寻找event.gallery.someAction();

    当您使用gallery 时,它会尝试在全局变量列表中找到它。

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

    【讨论】:

      猜你喜欢
      • 2011-08-12
      • 2011-06-07
      • 1970-01-01
      • 2010-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多