2017-03-09 51 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()(); 
相關問題