定义循环外的变量是否更好?

问题描述:

第二个比第一个好吗?定义循环外的变量是否更好?

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

在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

在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

在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

与其他语言不同,ActionScript不会为执行块(如for块)提供其自己的作用域。变量的最小范围是一个函数。所以对编译器来说,这两个例子都是一样的。实际上,这个实现是一种叫做“变量提升”的技术,编译器在范围开始之前移动变量的声明。

这有一些有趣的,如果意想不到的副作用;你可以在“声明”之前有效地“使用”一个变量。例如:

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

请注意,第一个跟踪不会失败。

无论如何,要记住的关键是变量是局部范围的功能。这在处理关闭时尤为重要。

+0

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