配列つまりArrayインスタンスをつくるには、つぎのふたつの書き方があります。どちらがよいのでしょうか。
var constructed_array:Array = new Array(); var literal_array:Array = [];
どちらにしたところで、大きな違いはありません。けれど、気分によって変えるのはやめましょう。統一はしないと、見にくいです。だとすると、やはりどちらがお得なのかは気にかかります。
ActionScript 3.0では、new演算子に続けて呼出すクラスと同名のメソッドでインスタンスをつくるのがお決まりです。このメソッドを「コンストラクタ」と呼びます。他方で、数値や文字列は値を直接書いてしまうのが普通でしょう[*1]。プログラムに直接書かれた値は、「リテラル」と呼ばれます。
Arrayインスタンスを配列アクセス演算子[]で書くのは、リテラルによるインスタンスのつくり方です。つまり、Arrayクラスのインスタンスは、コンストラクタメソッドとリテラルのどちらでも生成できます。できあがるインスタンスに、違いはありません。
Adobeは「Flex SDKコード記述に関する規則とベストプラクティス」という文書を公開しています[*2]。題名には「Flex」と書かれているものの、ActionScript 3.0のスクリプティングについての基本原則と捉えてよいでしょう。その「Arrayリテラル」の項は、インスタンスをリテラルでつくることとしています。
new Array()ではなく、配列リテラルを使用するようにします。
正しい記述例:[]誤った記述例[*3]:new Array()
ただし、長さを定めた空の配列は、Array()コンストラクタでつくってよいとされます。確かに、長さ100の配列をリテラルで書くのは無茶でしょう。
Arrayコンストラクタは、new Array(3)といったように、要素数を規定して配列を生成する時にだけ使用するようにします。この配列は[ undefined, undefined, undefined ]を意味するものであり、[ 3 ]ではありません。
配列のインスタンスをつくる速さで比べると、Array()コンストラクタの呼出しよりリテラルで書く方が勝るようです[*4]。その理由としては、Arrayクラスが内部的にふたつのコンストラクタをもつためではないかと考えられます。
原則として、Array()コンストラクタの引数は、エレメントとしてインスタンスに納められます。ところが、前項でも触れたように整数をひとつだけ渡すと、その長さでエレメントがundefinedのインスタンスがつくられます(表001)。このように引数の数やデータ型によって処理の異なる同じ名前のメソッドを定義することは「オーバーロード(多重定義)」と呼ばれます。
表001■コンストラクタの引数によってつくられる配列の違い
コンストラクタ呼出し |
引数の意味 |
つくられる配列 |
new Array() | エレメント | [] |
new Array(3) | 長さ | [undefined, undefined, undefined] |
new Array(0, 1, 2) | エレメント | [0, 1, 2] |
new Array("a") | エレメント | ["a"] |
それに対して、リテラルで書く場合、配列アクセス演算子[]の中にはエレメントしか入れられません。コンストラクタと違って、エレメントか長さかという判定が要らない分、速く扱えそうです。Adobe推奨で扱いが速く、記述も簡単ですので、配列のつくり方はリテラルに軍配が上がるのではないでしょうか。
エレメントを納めたArrayインスタンスも、配列アクセス演算子[]つまりリテラルでつくれます。前掲「Flex SDKコード記述に関する規則とベストプラクティス」は、その書き方まで細かく指示しています[*5]。括弧の内側、つまり配列アクセス演算子[]とエレメントとの間に半角スペースを置くようにというのです。
正しい記述例:[ 1, 2, 3 ]誤った記述例:[1, 2, 3]
大事なのは、統一することです。それさえできれば、あとは趣味の問題といって構わないでしょう。ただ、括弧の内側に半角スペースを入れるのなら、配列にインデックスを指定してアクセスするときや、さらに関数の定義・呼出しなどで使う丸括弧()についても、同じスタイルにすべきです。ところが、文書の推奨は次表002のように、エレメントを納めたArrayリテラルだけスタイルが異なっています。
表002■宣言・アクセスについてAdobeが推奨する記述
宣言・アクセス |
よい |
悪い |
Arrayリテラル | [ 1, 2, 3 ] | [1, 2, 3] |
[] | [ ] | |
配列アクセス | a[0] | a[ 0 ] |
関数定義・呼出し | f(a, b) | f( a, b ) |
ifステートメント | if (a < b) | if ( a < b ) |
switchステートメント | switch (n) | switch ( n ) |
forステートメント | for (var i:int = 0; i < n; i++) | for ( var i:int = 0; i < n; i++ ) |
[*1] 数値や文字列も、コンストラクタでつくることはできます。たとえば、文字列はその値を引数にして、「new String("文字列")」という呼出しで生成されます。けれど、あえてコンストラクタを使う意味は乏しく、リテラルの方が端的です。[ヘルプ]のString()コンストラクタの項にも、つぎのような注意が添えられています。
ストリングリテラルの方がStringオブジェクトよりもオーバーヘッドが少なく、一般的により簡単に使用できます。Stringオブジェクトを使用する特別な理由がある場合以外は、Stringクラスよりもストリングリテラルを使用することをお勧めします。
[*2] 日本語版の文書は、内容が完結していません。詳しくは、英語版の「Flex SDK coding conventions and best practices」を参照されるとよいでしょう。
[*3] 誤っている訳ではありません。原文の「Array literals」もつぎのように書いているだけですので、「好ましくない」というくらいの解釈が適切でしょう。
Do this:[]Not this:new Array()
[*4] wonderflのサンプルで速さを比べてみました(なお、「length」というのは、長さを0にしてインスタンスを再利用する手法)。
Initializing Arrays - wonderfl build flash online
[*5] 少し古い記事ではありますが、InfoQ「物議をかもしたAdobe Flexのコーディング規約文書」が参考になります。