Luar's Flash Playground:delete和undefined/null的分別
delete和undefined/null的分別 (25-04-2005)

對於Variable/Object或者Event Handler的刪除,很多人會用delete,或者將他們設定為undefined/null,表面看來沒有分別。我一直都是用delete,而且覺得設定為undefined/null不是Best Practice,看到別人的Code用這方法,特別不舒服,於是抽空做了一些試驗,看看三者究竟有沒有分別。

1. 對於Variable/Object:undefined和null可以是有分別,也可以是沒有分別

//var a;
b = null;
var c = 10;
delete c;
if (a == null) {
  trace("a is null");
}
if (a == undefined) {
  trace("a is undefined");
}
if (b == null) {
  trace("b is null");
}

if (b == undefined) {
  trace("b is undefined");
}
if (c == null) {
  trace("c is null");
}
if (c == undefined) {
  trace("c is undefined");
}

if (a == null and a == undefined) {
  trace("typeof a "+typeof a);
}
if (b == undefined and b == null) {
  trace("typeof b "+typeof b);
}
if (c == undefined and c == null) {
  trace("typeof c "+typeof c);
}
所有結果都是true,trace會輸出,undefined和null是沒有分別的。

但打開Debug Panel,只有b剩下:
null_debugpanel.jpg

如果將==改為!=,例如:

//var a;
b = null;
var c = 10;
delete c;
if (a != null) {
  trace("a is null");
}
if (a != undefined) {
  trace("a is undefined");
}
if (b != null) {
  trace("b is null");
}
if (b != undefined) {
  trace("b is undefined");
}
if (c != null) {
  trace("c is null");
}
if (c != undefined) {
  trace("c is undefined");
}
結果都是false,沒有trace會輸出,undefined和null是沒有分別的。

如果將==(equality)換成===(strict equality)後,輸出結果只剩下:

a is undefined
b is null
c is undefined
在嚴格Data Typing下,undefined和null是有分別的。(程式碼粗體的三句)

[下載範例]


2. 對於MovieClip Mouse相關Event Handler:delete和undefined/null是有分別

假設有兩個MovieClip(mc1,mc2)有以下程式碼:

mc1.onRelease = function() {
  trace(this);
  delete this.onRelease;
};
mc2.onRelease = function() {
  trace(this);
  this.onRelease = null;
  //this.onRelease = undefined;
};
當Mouse clicked,移走再移入mc1,Cursor已經由手指變回箭頭,但對於mc2,無論設定為undefined/null,移走再移入,Cursor仍然是手指,當然再Mouse clicked都不會有trace輸出。

[下載範例]


3. 對於原型鏈(Prototype Chain),delete和undefined/null是有分別

MovieClip.prototype.x = 10;

myMC.x = 20;
myMC.x = undefined;
trace(myMC.x); // undefined

myMC.x = 20;
delete myMC.x;
trace(myMC.x); // 10
對於不存在Property,Flash會沿Prototype Chain向上找(Resolve),因此決定不要一個Property時,想清楚是否需要向上引用,正確決定用delete或undefined。


4. 對於MovieClip.onEnterFrame:結果沒有分別,速度上有分別

刪除MovieClip.onEnterFrame,常見的做法有兩種:

delete this.onEnterFrame;
this.onEnterFrame = undefined;
這種做法在Flashcoder Mailing List過去是熱門討論的題目,delete被認為是Best Practice,首先,delete的東西,當然佔用較少Memory。在刪除onEnterFrame做法上,Get/Set設定速度是比delete object快,但是從MovieClip的EventHandler執行效率來說,Delete了,onEnterFrame是不存在,但設定為undefined,onEnterFrame這Handler是存在,變相浪費CPU繼續檢查onEnterFrame事件有什麼Function連繫著可以執行。另一方面,由於Prototype Chain原因,有人則會認為設定onEnterFrame為null有較佳效率,避免Flash每次都向上找。


5. ActionScript 2對非動態產生的onEnterFrame事件無法delete刪除

下載這範例執行,ball1.fla的關聯Class如下:

class ball1 extends MovieClip {
  function onEnterFrame() {
    _x += 20;
    if (_x>550) {
      delete this.onEnterFrame;
    }
  }
}
用delete是無法刪除onEnterFrame,MovieClip是不會停下,一直走出畫面,如果設定為undefined/null則可以使MovieClip停下。

對於動態產生的onEnterFrame事件,如ball2.fla的關聯Class:

class ball2 extends MovieClip {
  function ball2() {
    this.onEnterFrame = moving;
  }
  function moving() {
    _x += 20;
    if (_x>550) {
      delete this.onEnterFrame;
      //this.onEnterFrame = undefined;
    }
  }
}
無論是用delete或設定為undefined/null都可以使MovieClip停下。


其他參考資料

本文章由發表。
意見
"; print "沒有意見。
 "; } ?>
  • 哗.呢篇文章好正呀.
    学到好多野.
    以后真的是要正确决定使用delete与undefined/null了.
    受益唔少!!

    e路信峰於25-04-2005發表

  • 我正可以用这个!3Q!

    由KELU於25-04-2005發表

  • 我更习惯与用undefined
    因为flash所以属性在初始化以前都是undefined的(而非null)

    以前经常用del,但是发现有时候会不管用,也没仔细研究,就统一用undefined了

    由goldgoat於26-04-2005發表

  • Flash沒有清楚分開undefined和undeclared才給你這樣錯覺吧

    luar於26-04-2005發表

同組文章