Hatena::Groupactionscript

ConquestArrow.addEventListener();

2007-05-20

[][]AS3のスコープとint/uint型の宣言で基本的なところが解っていなかった件 03:18 はてなブックマーク - AS3のスコープとint/uint型の宣言で基本的なところが解っていなかった件 - ConquestArrow.addEventListener();

基本的な理解がなってなくてバグをだした件について自戒もこめて書いておく。


AS3ではint/uint型が追加された。一番使うのはやはりループ用のイタレータ変数だ。

for(var i:int=0; i<100; i++){
	...
}

AS3では、int/uint型の変数はデフォルトの値は0になる。

int データ型の変数のデフォルト値は 0 です。

データ型の詳細 -- Flex 2.01

uint データ型の変数のデフォルト値は 0 です。

データ型の詳細 -- Flex 2.01

つまりさっきのコードはこうも書ける。

for(var i:int; i<100; i++){
	...
}

この書き方のほうが便利なので、これでいいや、と使っていたところに落とし穴があった。

落とし穴は以下のコードで簡単にわかる。

var len:uint = 10;
var len2:uint = 1;
for(var i:uint; i<len; i++){
	for(var j:uint; j<len2; j++){
		trace("i:",i,"j:",j);
	}
	len2++;
}

これで期待する出力は以下だった。

i: 0 j: 0

i: 1 j: 0

i: 1 j: 1

i: 2 j: 0

i: 2 j: 1

i: 2 j: 2

i: 3 j: 0

i: 3 j: 1

i: 3 j: 2

i: 3 j: 3

(中略)

i: 9 j: 0

i: 9 j: 1

i: 9 j: 2

i: 9 j: 3

i: 9 j: 4

i: 9 j: 5

i: 9 j: 6

i: 9 j: 7

i: 9 j: 8

i: 9 j: 9

が、実際の出力は以下である。

i: 0 j: 0

i: 1 j: 1

i: 2 j: 2

i: 3 j: 3

i: 4 j: 4

i: 5 j: 5

i: 6 j: 6

i: 7 j: 7

i: 8 j: 8

i: 9 j: 9

どういうことかというと、

  1. 個人的にはint/uintで宣言すれば0で初期化される~と思っていたのだが、実際は単にデフォルトで0が入っているだけで初期化されているわけではなかった
  2. AS3のスコープはブロック単位ではない
  3. つまり、jの値は外側のforループの度に0になるのではなく以前の値を引き継ぐ

以下のようにすれば期待通りになる。

var len:uint = 10;
var len2:uint = 1;
for(var i:uint=0; i<len; i++){
	for(var j:uint=0; j<len2; j++){
		trace("i:",i,"j:",j);
	}
	len2++;
}

結論

  • 楽をしようとしてはいけない
トラックバック - http://actionscript.g.hatena.ne.jp/ConquestArrow/20070520