2011-11-23 21 views
5

第二個比第一個好嗎?定義循環外的變量是否更好?

FIRST:

var count:int=myArray.length; 
for(var i:uint=0;i<count;i++) 
{ 
    var str:String=myArray[i].label; 
    var somethingElse:Class=...; 
    var andAnotherThing:MyInstance=new MyInstance(somethingElse); 
    ... 
} 

第二:

var count:int=myArray.length; 
var str:String; 
var somethingElse:Class; 
var andAnotherThing:MyInstance; 
for(var i:uint=0;i<count;i++) 
{ 
    str=myArray[i].label; 
    somethingElse=...; 
    andAnotherThing=new MyInstance(somethingElse); 
    ... 
} 

謝謝。

+2

+1偉大的問題..正如我最初認爲這是顯而易見的,但很快通過其他答案意識到,這是非常明顯 – Chris

回答

7

在Actionscript和Javascript中,變量的作用域是函數而不是塊。這就是所謂的變量提升。

ActionScript 3.0 Variables

缺乏的塊級範圍內的一個有趣的含義是, 您可以閱讀或它宣告前,只要 函數結束之前宣佈寫入到一個變量。這是因爲稱爲提升的 技術,這意味着編譯器將所有變量聲明移動到函數的頂部。

所以有效的代碼會像這樣無論在哪裏,你的函數內聲明的變量:

var count:int; 
var str:String; 
var i:uint; 
var somethingElse:Class; 
var andAnotherThing:MyInstance; 

count = myArray.length; 
for(i=0;i<count;i++) 
{ 
    str=myArray[i].label; 
    somethingElse = ...; 
    andAnotherThing = new MyInstance(somethingElse); 
    ... 
} 

儘管如此,我還是喜歡到主要將其用於維護塊內聲明我的變量原因和一般的清晰度。

+0

啊,所以他們不會在每個循環中重新宣佈,對吧? – Francisc

+1

@Francisc Nope,他們不是,你正在爲循環的每次迭代設置相同的變量。您可以在調試器中驗證這一點,您會看到變量將包含每次迭代開始時的先前值。 – Peter

+0

太好了,再次感謝。 – Francisc

2

在Flash上​​,答案是沒關係。當涉及到變量聲明時,Flash很奇怪。 執行以下操作,看看會發生什麼:

for(var i:uint=0;i<count;i++) 
{ 
    var str:String=myArray[i].label; 
    var somethingElse:Class=...; 
    var andAnotherThing:MyInstance=new MyInstance(somethingElse); 
} 
var str:String=myArray[i].label; 

即使STR跑出範圍了的for循環,你會得到一個變量的重新定義警告,這意味着該變量將只在「初始化」一次for循環;

+0

謝謝,菲利普。 – Francisc

1

在ActionScript 3中,我不認爲它真的很重要。我相信在其他語言中,循環具有其自己的作用域含義,即在其中定義的變量不能在循環外訪問。

我認爲AS3的唯一區別是它如何影響可讀性。在我看來,第一個例子更好。

以前我經常限定的迴路爲了提高可讀性上面的迭代器,像這樣:

var i:MovieClip; 
for each(i in movieClipArray) 
{ 
    trace(i); 
} 

但自從進入各種語言,我已經把一切都包含一致性:

for each(var i:MovieClip in movieClipArray) 
{ 
    trace(i); 
} 
+0

謝謝,Marty。 – Francisc

2

與其他語言不同,ActionScript不會爲執行塊(如for塊)提供其自己的作用域。變量的最小範圍是一個函數。所以對編譯器來說,這兩個例子都是一樣的。實際上,這個實現是一種叫做「變量提升」的技術,編譯器在範圍開始之前移動變量的聲明。

這有一些有趣的,如果意想不到的副作用;你可以在「聲明」之前有效地「使用」一個變量。例如:

trace(test); // NaN 
var test:Number = 10; 
trace(test); // 10 

請注意,第一個跟蹤不會失敗。

無論如何,要記住的關鍵是變量是局部範圍的功能。這在處理關閉時尤爲重要。

+0

良好的洞察力,謝謝32位的孩子。 – Francisc