本節內容:
1.弱引用的使用原則
2.listener的不一樣和this關鍵字的指向。html
繼續上次的話題。在講listener 和 this關鍵字以前,咱們先來說講一個高級話題:
弱引用的使用原則。架構
繼續上次的話題。在講listener 和 this關鍵字以前,咱們先來說講一個高級話題:
弱引用的使用原則。ide
新手能夠不看,由於暫時用不到。但這個話題頗有必要。當設計大型RIA應用程序時,弱引用必需要了解。
弱引用從原則上來說,其引入是爲了防止無心識的對象保留(unintentional object retention)引發的內存泄漏。
什麼是無心識的對象保留?通常狀況下,對象的邏輯生命週期和實際生命週期應當相同。可是在某些狀況下,好比事件偵聽器機制,咱們可能會建立一個引用,它在內存中生存的時間比咱們預期的要長不少。好比說,下面的例子中,即便刪掉了偵聽器lis,但事件仍是能被繼續捕捉。這是因爲並無removeEventListenr,那麼系統中還會保留着對偵聽器的引用。
若是沒有把addEventListener中對偵聽器的持有改爲弱引用,那麼這個偵聽器會一直存在、耗掉內存不被人發覺。但若是設成了弱引用,那麼垃圾回收器過段時間後會將偵聽器佔用的內存回收,此時偵聽器從物理意義上才真正的被銷燬了。
在銷燬以前,這個偵聽器還會繼續存在,繼續做用。這就是爲何下例中雖然已經把useWeakReference設爲了true,可是仍是會有做用。
那麼什麼時侯垃圾回收器(Garbage Collector)纔會來回收呢?
唔,這要看它高興了,快的話10分鐘,慢的話一個月。哈哈,開玩笑,垃圾回收器的工做時間咋一看確實是不可測的,但也有規律可循。但這個問題探討在本系列教程中顯得過於艱深,黑羽會單獨撰文來講明垃圾回收器的部分工做機制。函數
那麼推論來了,咱們憑什麼要把useWeakReference設爲false呢?除非咱們有意要讓某個偵聽器在失去了其餘全部引用的時候還要工做,纔有可能這樣作。但誰會有這樣瘋狂的想法呢?道哥仍是包世宏?
因此,我建議,你們不妨養成習慣,把useWeakReference設爲true。
固然最好的作法是始終記得不用偵聽器了,必定要removeEventListener。在這一點上,咱們要堅持「始亂終棄」!!ui
public class LearnEvents extends MovieClip
{
function LearnEvents() {
var lis:Function = function () {
trace ("聽到了鼠標Click事件!");
}
var kingda_s:KingdaSprite = new KingdaSprite(0xFFCC00, "kingdaSquare");
addChild(kingda_s);
kingda_s.addEventListener(MouseEvent.CLICK, lis, false, 0, true); //瞧,最後一個參數,已經把弱引用設爲true了
lis = null; //這一句,我已經從邏輯上刪掉lis了,你們做證啊
trace ("偵聽器還在嗎?:"+ lis); //lis也確實指向null了。但你只要繼續點擊方塊,你會發現Click事件仍然被捕捉到。
}
}
}
import flash.display.Sprite;
import flash.events.MouseEvent;this
//這個類就是畫一個矩形,
class KingdaSprite extends Sprite {
public var nickname:String;
public var ColorNum:uint;
//colorNumber就是#ffcc00這種類型的數,在AS3中推薦用新的uint型來標記它
public function KingdaSprite(colorNumber:uint, nameString:String) {
ColorNum = colorNumber;
nickname = nameString;
graphics.beginFill(ColorNum);
graphics.drawRect(0,0,100,100);
graphics.endFill();
}
}spa
Listener和As2.0有何不一樣,和this關鍵字的「改進了的記憶力」
DOM Level 3中規定的是用Object來作listener。該Object有用來處理事件的方法(method)。
AS3雖然是按照DOM Level 3事件機制設計的,但也不徹底聽話,有本身獨立的想法。在AS3中,偵聽器就是函數。也只能用函數來偵聽。
其實在ActionScript3中,Function實質也是一種特殊的Object,和AS2.0有類似之處。
見個人文章:
ActionScript高級技巧:深刻了解Function
所以AS3.0爲何限定用Function,這和它的架構有關,不細說了。
但有趣的是,在AS3.0中,對IEventDispatcher的定義中,仍然按照DOM3標準用Object來作Listener。見黑羽上一篇教程和隨後的評論。設計
那麼問題來了,function中this關鍵字的指向會怎樣?
AS2.0開發者對AS2.0 事件機制中 this關鍵字的水性楊花應該深有認識。若是用function作偵聽器,那麼誰發出事件,this就指向誰。這就等於對象之間亂搞關係,啊呀呀。因此MM派了一個Delegate代理警察類來管理。唉,糜亂的歲月不堪回首啊。代理
kingda_btn.addEventListener("click", lisFunc); //點一下button,看看指向誰。htm
回到ActionScript 3.0,來看看堅決的夫妻關係,黑羽總結爲:嫁雞隨雞,嫁狗隨狗,什麼都不嫁,那就屬於global。我靠,讀一下,還挺押韻。你們也好記。
簡單的解釋一下,函數在哪一個對象裏(應該叫method),那麼this就指向誰。不在對象裏,那麼就指向global。
public class AddListener extends Sprite {
public function AddListener() {
//用package外面定義的類KingdaSprite建立一個實例,因爲同文件中,因此不用import啦
var outsideChild:KingdaSprite = new KingdaSprite(0x00FF00, "outside_sprite");
addChild(outsideChild);//沒有了這一句,你啥都看不到。
outsideChild.addEventListener(MouseEvent.CLICK, inclassHandler);//註冊類裏面的偵聽器
outsideChild.addEventListener(MouseEvent.CLICK, outsideHandler);//註冊類外面的偵聽器
}
private function inclassHandler(event:MouseEvent):void {
trace("類裏面的偵聽器偵聽到MouseEvent事件: " + event);
trace("this關鍵字指向:"+this);
}
}
}
function outsideHandler(event:MouseEvent):void {
trace("類外面的偵聽器偵聽到MouseEvent事件: " + event);
trace("this關鍵字指向:"+this);
}
import flash.display.Sprite;
import flash.events.MouseEvent;
//這個類就是畫一個矩形,而後你點擊這個矩形會發出標準鼠標click的事件class KingdaSprite extends Sprite { public var nickname:String; public var ColorNum:uint; //colorNumber就是#ffcc00這種類型的數,在AS3中推薦用新的uint型來標記它 public function KingdaSprite(colorNumber:uint, nameString:String) { ColorNum = colorNumber; nickname = nameString; graphics.beginFill(ColorNum); graphics.drawRect(0,0,100,100); graphics.endFill(); }}