当在嵌套或内联函数中访问 "this" 时,[object global] 到底是什么?

What [object global] is exactly, when "this" is accessed inside a nested or inline function?

代码如下:

package {
    import flash.events.*;
    import flash.display.*;

    public class SomeDocumentClass extends MovieClip {

        public var abc: MovieClip;
        public var test_var = 12345;

        public function SomeDocumentClass() {
            //abc is an instance name of a movieclip placed on stage
            abc.addEventListener(MouseEvent.CLICK,
                function () {
                    trace(this); 
                });
            abc.addEventListener(MouseEvent.CLICK, abc_CLICK)
        }

        function abc_CLICK(e: Event): void {
            trace(this); 
        }

    }

}

输出是:

[object global]

[object SomeDocumentClass]

我也查了一下,[object global]实际上连函数本身都不是。那又是什么呢?

匿名函数(也称为函数表达式)是 全局 作用域与定义函数(也称为函数语句)局部 作用域。

匿名函数

  • 不能作为方法使用
  • 只存在于定义的范围内
  • 只能在定义的范围内调用
  • 可以在代码中的任意位置调用
  • 可以重新分配一个新值或删除

定义函数

  • 可以作为对象的方法
  • 存在于它定义的对象中
  • 可以在代码中的任意位置调用
  • 无法删除或更改

举个例子:

this 在匿名函数中

[trace] [object global]
[trace] global
[trace] <type name="global" base="Object" isDynamic="true" isFinal="true" isStatic="false">
[trace]   <extendsClass type="Object"/>
[trace]   <constant name="FLASH10_FLAGS" type="uint" uri="avmplus"/>
~~~~~~~~~~~~
[trace]   </method>
[trace] </type>

this 在定义函数中

[trace] [object Main]
[trace] Main
[trace] <type name="Main" base="flash.display::Sprite" isDynamic="false" isFinal="false" isStatic="false">
[trace]   <extendsClass type="flash.display::Sprite"/>
~~~~~~~~~~
[trace]   </metadata>
[trace] </type>

ActionScript cut/paste 完整示例:

package {
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    import avmplus.getQualifiedClassName;
    import flash.utils.describeType;

    public class Main extends Sprite {
        var button:CustomSimpleButton;

        public function Main() {
            button = new CustomSimpleButton();
            button.addEventListener(MouseEvent.CLICK,
                    function () {
                        trace(this);
                        trace(getQualifiedClassName(this));
                        trace(describeType(this));
                    });
            button.addEventListener(MouseEvent.CLICK, onClickButton);
            addChild(button);
        }

        function onClickButton(event:MouseEvent):void {
            trace(this);
            trace(getQualifiedClassName(this));
            trace(describeType(this));
        }
    }
}

import flash.display.Shape;
import flash.display.SimpleButton;

class CustomSimpleButton extends SimpleButton {
    private var upColor:uint   = 0xFFCC00;
    private var overColor:uint = 0xCCFF00;
    private var downColor:uint = 0x00CCFF;
    private var size:uint      = 80;

    public function CustomSimpleButton() {
        downState      = new ButtonDisplayState(downColor, size);
        overState      = new ButtonDisplayState(overColor, size);
        upState        = new ButtonDisplayState(upColor, size);
        hitTestState   = new ButtonDisplayState(upColor, size * 2);
        hitTestState.x = -(size / 4);
        hitTestState.y = hitTestState.x;
        useHandCursor  = true;
    }
}

class ButtonDisplayState extends Shape {
    private var bgColor:uint;
    private var size:uint;

    public function ButtonDisplayState(bgColor:uint, size:uint) {
        this.bgColor = bgColor;
        this.size    = size;
        draw();
    }

    private function draw():void {
        graphics.beginFill(bgColor);
        graphics.drawRect(0, 0, size, size);
        graphics.endFill();
    }
}