2017-03-09 54 views
1

我的背景在JavaScript中很重。我对ES5和ES6都有非常深入的了解。在工作中,我最近分配了一个涉及使用AS2的较旧Flash应用程序的项目。我的理解是,ActionScript与ES5非常相似,但具有类和可选的严格类型(类似于TypeScript和Flow)以及一些其他经典OO功能。目前为止相当简单,但我无法理解如何在ActionScript中使用this和引用。JavaScript和ActionScript中的“this”之间的区别

这是我对JavaScript的理解。 this在函数可以参考:

  • 甲绑定变量,如果用Function.bind()(以及Function.call()和Function.apply()),其不能在绑定函数被改变,例如:

function func() { 
    return this.number; 
} 

var bound = func.bind({ number: 2 }); 
console.log(bound()); // 2 
  • 一个目的,如果被调用的函数作为对象的方法,例如:

function func() { 
    return this.number; 
} 

var obj = { number: 2, func: func }; 
console.log(obj.func()); // 2 
  • 一个类的实例中,如果该功能是在这个类的原型定义,例如:

function Class() { 
    this.number = 2; 
} 
Class.prototype.func = function func() { 
    return this.number; 
} 

console.log(new Class().func()); // 2 
  • 全局对象,如果调用函数时没有任何形式的结合或连接到它的对象或实例,例如:

var number = 2; 

function func() { 
    return this.number; 
} 

console.log(func()); // 2 

在ActionScript的事情似乎有点不同。一方面,你可以访问类的成员,而不this,如果你是在该类的方法,类似于像C#和Java语言中这样做:

class MyClass { 
    private var number:Number = 2; 

    public function func():Number { 
     return number; 
    } 
} 

trace(new MyClass().func()); // 2 

而且,动作脚本标准库似乎并不具备一个Function.bind()方法,虽然它确实有Function.apply()Function.call(),它们看起来像JavaScript变体一样工作:http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/2/help.html?content=00001072.html#265677。也似乎没有原型,这是有道理的,因为基于我的理解,类是更抽象的语法结构而不是函数(就像C#/ Java)。

所以我的问题是,除了缺少Function.bind()Function.prototype,ActionScript和JavaScript之间的规则是相同的吗?

另外,如果我这样做,会发生什么:

class SomeClip extends MovieClip { 
    private var childClip:MovieClip; 
    private var number:Number = 2; 

    public function SomeClip() { 
     this.onLoad = function() { 
      // SomeClip onLoad hander, `this` will be the SomeClip instance 

      childClip._visible = true; // How is childClip resolved here? 

      childClip.onRelease = function() { 
       // childClip onRelease handler, `this` will be childClip 

       trace(number); // How is number resolved here? 
      }; 
     }; 
    } 
} 

基本上,如果你在一个事件处理程序,或其他一些松散的函数,不是类的方法来访问的成员不this什么发生?我猜想在第一种情况下,它将解析为this.childClip并按照预期工作,但在第二种情况下,解决方案将失败,因为onRelease处理程序的关闭将不包含对SomeClip实例的引用。

+0

AS2有点像ES3。 AS3基于废弃的ES4规范(规则在类和类似方面是不同的)。 ES5 +的功能都不像“Function.prototype.bind”。 –

+0

ES中的'this'只是指当前的执行上下文,它由当前的函数/方法eval确定,并且存在'this'指向'window'的全局执行上下文。 – Li357

回答

2

我看到到目前为止写的评论更关注于JS,所以我会尽我所能从ActionScript的角度回答。

在AS2/AS3的世界中,定义为类的方法的函数将其值this的值绑定到该类。这是许多具有现代类的高级语言的典型特征,例如Java,Haxe等。因此,在ActionScript中,除了变量名可能被阴影所覆盖的情况之外,您很少会发现需要使用this关键字功能参数:

public function Point(x:Number = 0, y:Number = 0) 
{ 
    // A rare but necessary use-case of "this" in AS2/AS3 
    this.x = x; 
    this.y = y; 
} 

在另一方面,如果你提供的功能是匿名在你写的例子,行为取决于你是否在前面加上this

childClip.onRelease = function() { 
    trace(number); 
}; 

在这种情况下, ActionScript是能够确定number是该类的成员,并将打印2就像你期待的那样。这是因为解释器在栈中查找下一个最接近的东西。换句话说,除了this之外,你知道它需要执行查找,所以你不明确。

但是,如果您改为trace(this.number),则会发现您获得undefined(甚至可能有错误)。这是因为this不是该类的成员变量,现在指向一个类似于JS的“全局对象”。为了避免与全局对象跳舞,这是为ActionScript开发者定义所有的听众作为类的实例方法,常见的做法:

class MyClass extends EventDispatcher 
{ 
    private function MyClass() 
    { 
     addEventListener(Event.CHANGE, onChangeEvent); 
    } 
    private function onChangeEvent(e:Event) { 
     trace(this); // refers to this class, and no need for bind() like JS 
    } 
} 

良好的组织AS3代码几乎从来不会包含联匿名功能,因为它更容易处理垃圾回收通过使用明确的函数引用。

最后一两件事要注意的 - 你可以期望在ActionScript中经常Objects方法的行为类似于JavaScript的地方周围路过他们通过事件侦听器将导致this情况下丢失的功能,而Flash不会做魔术查找以找到您引用的变量:

var obj = { 
    func: function() { 
     trace(this); // weird global object 
    } 
}; 
addEventListener(Event.CHANGE, obj.func); 

希望有所帮助!

+0

这正是我正在寻找的。谢谢! – jchitel

+0

完全没问题! :) – Cleod9

2

在AS2函数没有绑定并获得“this”引用(显然是通过函数。在电话的那一刻起申请或由对象引用):

function getIndex() 
{ 
    trace(this.index); 
} 

var A = {index:1, getIndex:getIndex}; 
var B = {index:2, getIndex:getIndex}; 

A.getIndex(); // 1 
B.getIndex(); // 2 
B.getIndex.apply(A); // 1 

结合的方法对某些对象被称为“委托”:http://help.adobe.com/en_US/AS2LCR/Flash_10.0/help.html?content=00001842.html#1001423简而言之,函数是对象也是一样,你可以创建一个具有引用特殊功能对象这两个方法来调用和“此”对象传递:

function getIndex() 
{ 
    trace(this.index); 
} 

function bind(method, target):Function 
{ 
    var result:Function = function() 
    { 
     // arguments.callee is always a reference 
     // to the current function object 
     arguments.callee.method.apply(arguments.callee.target); 
    } 

    result.method = method; 
    result.target = target; 

    return result; 
} 

var A = {index:1}; 
var B = {index:2}; 

A.getIndex = bind(getIndex, A); 
B.getIndex = bind(getIndex, B); 

A.getIndex(); // 1 
B.getIndex(); // 2 
B.getIndex.apply(A); // 2 

然后,如果你不使用“this”引用,一旦你解决它的名字有些变量有在其中搜索这样几个背景一个变量,顺序为:

  • 本地函数变量
  • 本地包装函数变量(这个人是真正可怕的,没有人真正知道在哪里这些变量存在,它是一种有效的内存泄漏)
  • 影片剪辑,保存功能代码,局部变量
  • 全局变量

播放用下面的代码,评论一些“指数”变量,你会看到它:

// Global variable. 
_global.index = 6; 

// MovieClip local variable. 
var index = 5; 

function wrap():Function 
{ 
    // Wrapper function local variable. 
    var index = 4; 

    return function() 
    { 
     // Function local variable. 
     var index = 3; 
     trace(index); 
    } 
} 

wrap()(); 
相关问题