サイトトップ

Director Flash 書籍 業務内容 プロフィール

Optimizing Performance of ActionScript 3.0

Chapter 03 まとめたデータの扱い

□03-05 Arrayインスタンスはコンストラクタでなくリテラルでつくる

Arrayインスタンスつまり配列は、Array()コンストラクタと配列アクセス演算子[]を使った(「リテラル」と呼ばれます)ふたつの書き方でインスタンスがつくれます。ふたつを比べると後者の方が扱いは速くてお得です。つまり結論は、インスタンスを配列アクセス演算子[](リテラル)でつくりましょうということになります。けれど、その理由を少しかみ砕いてご説明しましょう。

    【配列をリテラルでつくった方がよいのは】
  1. Adobeの推奨するスクリプトの書き方
  2. 処理が速い

03-05-01 コンストラクタとリテラル
ActionScript 3.0では、new演算子に続けてクラスと同名のメソッド、つまりコンストラクタメソッドでインスタンスをつくるのがお決まりです。もちろん、Arrayクラスのインスタンスもコンストラクタを呼出して生成できます。

var my_array:Array = new Array();

クラスの中には、決められた書き方で直接値をつくれるものがあります。Arrayクラスはそのひとつです。配列アクセス演算子[]を使うと、コンストラクタを呼出すことなくインスタンスができ上がります。プログラムに直接書かれた値は「リテラル」と呼ばれます。

var my_array:Array = [];

Word 03-05-001■リテラル
「リテラル」とは、プログラム(のソースコード)に直接記載される値を示します。変数から値を取出したり、関数(メソッド)の戻り値を受取るのではなく、文字列(String型)や数値(Number/int/uint型)を直接記述する場合がその典型です。たとえば、つぎの代入式の右辺値は、いずれもリテラルです。

var product_str:String = "Flash Professional CS5";
var nPlayerVersion:int = 10;

値をリテラルで記述できるデータの例については、後述Tips 03-05-001「いろいろなリテラル」をお読みください(なお、ヘルプ[ActionScript 3.0の学習] > [ActionScript言語とシンタックス] > [シンタックス]の「リテラル」の項参照)。

[*筆者用参考] e-Words「リテラル


Tips 03-05-001■いろいろなリテラル
もっとも基本的なリテラルとしては、数値(Number/int/uint型)や文字列(String型)、ブール(論理値)値(Boolean型)が挙げられます。あとはつぎのように、Objectクラスのほか、XMLやRegExp(正規表現)などのインスタンスがリテラルで書けます。

var myObject:Object = {};

var my_xml:XML = <cs5>
  <product suite="Web">
    <name>Flash</name>
    <price>699</price>
  </product>
  <product suite="Web">
    <name>Dreamweaver</name>
    <price>399</price>
  </product>
</cs5>;

var myPattern:RegExp = /AS ?3\.0|AS ?3?/g;

もちろん、コンストラクタでもリテラルでも、できあがるArrayインスタンスに違いはありません。このふたつを、スクリプトの書き方と処理の速さのふたつの麺から比べてみます。


03-05-02 見やすいスクリプトを書く
つくられるインスタンスは同じだからといって、コンストラクタとリテラルを気分によって使っているとスクリプトが読みにくくなります。よいプログラムは後あとまで使いますし、さらに手を加えることも考えなければなりません。また、共同で開発をしたり、自分以外の人が中身を見ることもありえます。ですから、半年後の自分や他の人にもわかりやすいように、書き方を整えるべきでしょう。

Adobeは「Flex SDKコード記述に関する規則とベストプラクティス」<http://opensource.adobe.com/wiki/display/flexsdk/Coding+Conventions-ja>という文書を公開しています(図001)。題名には「Flex」と書かれているものの、ActionScript 3.0のスクリプティングについての基本原則と捉えてよいでしょう。この「規則に従うことで、ソースコードの体裁の一貫性、整頓性および専門性を確保することができます」と述べています。

図03-05-001■Flex SDKコード記述に関する規則とベストプラクティス

「ソースコードの体裁の一貫性、整頓性および専門性を確保する」ための規則とされている。


Tips 03-05-002■英語版「Flex SDK coding conventions and best practices」
「Flex SDKコード記述に関する規則とベストプラクティス」は、まだ内容が完結していません。英語版の「Flex SDK coding conventions and best practices」<http://opensource.adobe.com/wiki/display/flexsdk/Coding+Conventions>の方が進みは早いようです。

この文書の「Arrayリテラル」の項は、配列のインスタンスをコンストラクタでなく、リテラルでつくるよう勧めています。

スクリプト03-05-001【○】Adobeはリテラルによる配列の生成を推奨する
  1. []

スクリプト03-05-002【×】Adobeはコンストラクタによる配列の生成は推奨しない
  1. new Array()

Tips 03-05-003■「Flex SDKコード記述に関する規則とベストプラクティス」は推奨を説く
「Flex SDKコード記述に関する規則とベストプラクティス」は、Array()コンストラクタを使うのがつぎのように「誤った記述例」だと表現しています。しかし、決して間違ってなどいません。

正しい記述例:

[]


誤った記述例:

new Array()

英語版は以下のように、コンストラクタでなくリテラルを用いるようにと説いているだけです。したがって、コンストラクタを使うのは勧められない、というくらいに理解すべきでしょう。

Do this:

[]


Not this:

new Array()

Array()コンストラクタメソッドに整数をひとつ引数として渡すと、その長さ(Array.lengthプロパティ)でエレメントはすべてundefinedの配列ができ上がります。このように長さを定めた配列は、Adobeもつぎのようにコンストラクタでつくることを認めます。長さ100の配列がほしい場合を考えてみれば、コンストラクタでなくリテラルで書くのは無茶でしょう。

Arrayコンストラクタは、new Array(3)といったように、要素数を規定して配列を生成する時にだけ使用するようにします。この配列は[ undefined, undefined, undefined ]を意味するものであり、[ 3 ]ではありません。

Adobeの文書では、リテラルを勧める理由は明らかにしていません。おそらく、スクリプトが書きやすく、見る側にもコンストラクタと比べてことさらわかりにくいことはないからでしょう。

Tips 03-05-004■Adobeは基本的にリテラルを推奨
前述Tips 03-05-001「いろいろなリテラル」に掲げたオブジェクトについても、Adobeの文書はリテラルを勧めています。とくにXMLやRegExpインスタンスについては、リテラルの方が端的で見やすく感じられます。そうすると全体として統一するなら、(とくに必要性がある場合を除き)インスタンスはコンストラクタでなくリテラルで書くというのは納得できます。


03-05-03 コンストラクタとリテラルのどちらが速いか
Arrayインスタンスをつくる速さで比べると、Array()コンストラクタの呼出しより、リテラルで書く方が勝ります。その理由として考えられるのは、Arrayクラスが内部的にふたつのコンストラクタメソッドをもつことです(図03-05-002)。

図03-05-002■Arrayクラスには内部的にコンストラクタメソッドがふたつ定義されている

渡される引数の数とデータ型により、異なるメソッドが呼出される。

原則としては、Array()コンストラクタに渡す引数の数に定めはなく、それらはでき上がる配列のエレメントとして納められます。けれど、前項の終わりに触れたとおり、整数の引数をひとつだけ渡したときは、その長さでエレメントはundefinedの配列がつくられます。このように、引数の数やデータ型によって処理の異なる同じ名前のメソッドを定義することは「オーバーロード(多重定義)」と呼ばれます。

表03-05-001■コンストラクタの引数によってつくられる配列の違い
コンストラクタ呼出し 引数の意味 つくられる配列
new Array() エレメント []
new Array(3) 長さ [undefined, undefined, undefined]
new Array(0, 1, 2) エレメント [0, 1, 2]
new Array("a") エレメント ["a"]

つまり、コンストラクタを呼出しすと、内部では引数の値がエレメントなのか長さなのか切り分けなければなりません。それに対して、リテラルで書けば、配列アクセス演算子[]に入れるのはエレメントに決まっています。判定の要らない分処理が速いというのば理解できます。


03-05-04 Arrayインスタンスはリテラルでつくる
読みやすいスクリプトを書くためには、インスタンスはコンストラクタとリテラルのどちらでつくるのか、統一しておくべきです。そして、前述のとおり、スクリプトの書き方としては、Adobeも推奨するリテラルの方がよさそうです。そして、インスタンスをつくる速さも、リテラルが優れていました。

したがって、とくに必要のある場合を除いて、配列はリテラルでつくった方がよいでしょう。なお、必要がある場合としては、Adobeの文書で示されていた長さを定めた(エレメントはundefinedの)インスタンスをつくるときが挙げられます。

[*筆者用参考]

Initializing Arrays - wonderfl build flash online



作成者: 野中文雄
更新日: 2011年2月20日 Word 03-05-001「リテラル」を追加。
作成日: 2011年1月30日


Copyright © 2001-2011 Fumio Nonaka.  All rights reserved.