2011-01-19 50 views
2

有人能指出为什么下面的代码在第一种情况下会失败:ActionScript 3的 '本' 的问题

CASE 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(); 
}); 

CASE 2

this.gallery.addEventListener(GalleryEvent.WHATEVER, function(event:*) { 
    // This works fine 
    gallery.someAction(); 
}) 

在这种情况下是否有关于this使用的规则?

+1

尝试添加监听* *没有**使用匿名功能。 – 2011-01-19 00:49:28

回答

6

这是因为“范围链”。在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(); 
    } 
} 

在这种情况下,当你的,说:“什么是对的scopechain这里”时,scopechain看起来像这样(下面是第一个范围的行将要检查第1名):功能f()

  • 一个实例,用变量localvarinnerfunc
  • 类的当前实例C
  • ŧ他类C
  • 全球范围

认识到这一点很重要,当代码var innerfunc: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(); 
}) 

我能在这个问题上永远持续下去 - 我觉得很有意思:-)

4

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

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

当您使用gallery,它试图全局变量的列表中找到它。

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