Actionscript 3“这个”问题

发布于 2024-10-12 20:26:22 字数 607 浏览 3 评论 0原文

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

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 的使用是否有任何规则在这种情况下?

Could someone point out why does the following code fail in the first case:

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

Are there any rules regarding this usage in such cases?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

〆一缕阳光ご 2024-10-19 20:26:22

这是因为“作用域链”。在 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() 的一个实例,带有变量 localvarinnerfunc
  • 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();
})

我可以永远继续这个主题 - 我发现它很有趣:-)

This is because of the "scope chain". In ActionScript 3 (which is ECMAScript compliant -- JavaScript has the same behavior described below), there is a built-in list of "places" that is used to resolve any named variable, called the scope chain. E.g. when in a "normal" method of a class, the scope chain looks like this:

  • The current instance object (the same as this)
  • The class object (used for accessing static variables)
  • The global scope (used for accessing globals, e.g. Math)

But when you are in an anonymous inner function, the scope chain has one more entry at the top, representing the method that was in scope at the point in the time when the anonymous function was created. So for example, suppose you have this code:

class C {
    var membervar:int;

    function f() {
        var localvar:int;

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

        innerfunc();
    }
}

In this case, when you are the the line that says "what is on the scopechain here", the scopechain looks like this (with the first scope below being the first place that will be checked):

  • One instance of the function f(), with variables localvar and innerfunc
  • The current instance of class C
  • The class C
  • The global scope

It's important to realize that that when the line of code var innerfunc:Function = function()... executes, it is creating the Function object on the fly, and setting its scope chain on the fly. So for example, suppose you had this (confusing) code, which, given an argument an_arg, returns a Function which, when invoked, will print the value of an_arg:

function f(an_arg:int):Function {
    return function():void {
        trace(an_arg);
    }
}

Each function returned by calls to f() has its own scope chain, pointing to different instances of f(). So:

var func1:Function = f(3);
var func2:Function = f(4);

func1(); // prints 3
func2(); // prints 4

The common way to avoid this problem, if you really want to refer to this in the inner function rather than relying on the magic of the scope chain, is to create a temporary variable called self in the outer function -- in the case of your sample code, it would look like this:

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

I could go on forever on this subject -- I find it fascinating :-)

蝶…霜飞 2024-10-19 20:26:22

因为您传递此函数 function(event:*) 这意味着它是在该范围内执行的。

因此,当它尝试查找 this 时,它会查找 event.gallery.someAction();

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

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

because you're passing this function function(event:*) which means it is executed in that scope.

so when it tries to look for this it is looking for event.gallery.someAction();

when you use gallery, it tries to find it within the list of global variables.

One way to verify this is to add a trace(this) and see what happens.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文