サイトトップ

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

Macromedia Flash非公式テクニカルノート

ActionScriptとその基本概念について

ID: FN0506003 Product: Flash

Platform: All
Version: MX 2004 and above

本稿では、ActionScriptとその背景にあるプログラミングや仕様上の基本概念について解説します。基本とはいえ、概念説明ですので、必ずしも初心者向けの内容ではありません。スクリプトについての基礎知識が前提とされます。その中でも中級者向けと思われる節には、【Advanced】と付記してあります。基本用語は「Word」という項目で、囲み記事としました。また、中級者以上向けのトピックも、「Advanced Topic」という囲み記事にしています。ご興味や知識レベルに応じて、ご参照ください。

●01 ECMAScriptとしてのActionScript
ActionScriptは、Flash 5から導入されたオブジェクト指向プログラミング(スクリプト)言語です。ActionScriptは、ECMA-262仕様に準拠します。ECMA-262は、JavaScriptの国際標準とされています。したがって、基本的な文法は、JavaScriptと同一です。実際、ArrayやDate、Math、Objectなど、JavaScriptとまったく同じクラス(オブジェクト)も、数多く実装されています。ECMA-262に準拠したスクリプトは、とくに欧米ではECMAScript(エクマスクリプト)と呼ばれます。

Word□ECMA
1961年にEuropean Computer Manufacturer Associationとして、ヨーロッパのコンピュータメーカーを中心に設立された組織です。日本語では、ヨーロッパ(欧州)電子計算機工業会と訳されます。1994年に、名称をEcma Internationalと改めました。おもに、情報通信技術に関する標準を策定しています。現在では、世界各地に会員企業を持つ国際団体となっています。2003年11月17日に、Macromeida社も正式に参加しました。

参考: IT Pro「米Macromedia,Ecma Internationalに正式参加しECMAScript策定に協力

JavaScriptは、Netscape Communications社(1998年に現AOL Time Warner社に買収)とSun Microsystems社が共同開発したスクリプト言語です。それに対抗したMicrosoft社が自社技術を追加・拡張して、JScriptを開発しました。NetscapeとMicrosoftの仕様は細部で異なっていたため、両社も参加して、ECMAがECMAScriptとして標準化しました。

こうした経緯ですので、JavaScriptもJScpritも、厳密にはECMA-262と一致していない部分があります。これはActionScriptでも同様で、ECMA-262に完全に準拠している訳ではありません。

●02 スクリプトとは【Advanced】
ActionScriptとかJavaScriptでいう「スクリプト」とは、どういう意味でしょう。英語でscriptは、「脚本」や「台本」のことです。舞台とかドラマの進行や演技の内容を指示するものが、scriptという訳です。プログラムでいうscriptは、処理手順を命令として記述したものです。

もっとも、このように説明すると、プログラムすべてが含まれてしまいそうです。もともとは、小規模の処理手順をすばやく作成することがおもな目的とされる、簡易プログラムが「スクリプト」と呼ばれました。一般のプログラミング言語に比べて機能は少ないものの、習得しやすく文法も簡便なことが特徴です。

しかし、スクリプト言語も改訂が進み、機能が拡張されていきます。すると、必ずしも容易とも簡便ともいえなくなってきました。そこでプログラミング言語のなかでも、とくに「インタプリタ形式」で実行されるものが、一般に「スクリプト」と呼ばれます。

Word□スクリプト
プログラマの書いたソースコードをコンピュータの理解できる機械語に変換するプロセスを自動化して、簡単に実行できるようにした簡易プログラムを「スクリプト」と呼びます。

参考:「Javascriptとは」 「スクリプトとは

interpreterというのは、「通訳」のことです。プログラミング言語のインタプリタは、記述されたプログラム(「ソースコード」といいます)をコンピュータが理解・実行できる形式いわゆる機械(マシン)語(「オブジェクトコード」または「ネイティブコード」)に翻訳します。インタプリタ形式のプログラミング言語は、実行時にこのインタプリタを介して処理を実行します。

インタプリタ形式に対するプログラムの実行形態は、「コンパイル形式」です。compileというのは、「まとめる」という意味です。具体的には、これも機械(マシン)語に翻訳する処理を指します。しかし、インタプリタと異なるのは、実際の処理を行う前にこの翻訳を終えて、実行ファイルを作成してしまうということです。つまり、実行ファイルは、オブジェクトコードで直接処理を行います。

インタプリタ形式がその場で通訳を介してコンピュータとやり取りするのに対して、コンパイル形式ではネイティブスピーカーの代役を立ててしまうということです。あるいは映画なら、吹替えをすると考えればよいでしょう。

インタプリタ形式の方が、手軽にプログラムが試せます。また、MacintoshとWindowsそれぞれの通訳を雇うだけで、複数のオペレーティングシステムに対応できます。Flash(SWF)ムービーに対して通訳の役割を担うのは、Flash Playerです。MacintoshでもWindowsでも、対応するFlash Playerがインストールされていれば、同じSWFムービーを再生することができます。

コンパイル形式は、準備に手間がかかります。しかし、吹替えされた映画は、観客にリアルタイムでストーリーが伝わります。つまり、実行時の処理が、最適化されるのです。そのため、処理スピードが問題とされるような大規模開発には、コンパイル形式の言語が用いられます。コンパイル型言語の代表として、CやC++が挙げられます。

もっとも、FlashのActionScriptは、記述したスクリプトをそのまま直ちに実行できる訳ではありません。一旦SWFに書出す必要があります。このとき、ActionScriptはソースコードのまま書出されるのでなく、「バイトコード」と呼ばれるFlash Player向けの命令に変換されます。その命令は、MacintoshやWindowsといったプラットフォームを問わず共通のSWFファイル形式で、Flash Playerの通訳を必要とします。バイトコードは、ソースコードとネイティブコードのいわば中間言語にあたります。

Word□バイトコード
「バイトコード」とは、特定のオペレーティングシステム(OS)やハードウェアに依存しない命令で記述されたプログラムです。ソースコードとネイティブコードの中間の形式に当たります。命令をすべて1バイトで表現し、プログラムのサイズを小さく抑えていることから、バイトコードと呼ばれるようになりました。

バイトコード形式のプログラムを動作させるには、バイトコードを解釈してその環境のネイティブコードに変換する「仮想マシン」と呼ばれるソフトウェアが必要です。Flash Playerは、この仮想マシンの役割を果たします。アプリケーションをバイトコードで配布すれば、仮想マシンが実装されているOS上なら、環境を問わずにそのアプリケーションを実行できることが利点です。

バイトコード形式をサポートしているプログラミング言語の代表はJavaです。そのため、Javaのバイトコード(Javaバイトコード)のことを単に「バイトコード」と呼ぶこともあります。

ActionScriptでは、FlashムービーをSWFに書出すことを、「コンパイル」ということがあります。ソースコードを、Flash Player上で実行するのに適した形式に変換するからです。しかし、コンパイル形式の言語のように、機械(マシン)語の実行ファイルに変換する訳ではありません。バイトコードを解釈してそのコンピュータのネイティブコードに変換するFlash Playerを必要とします。

つまり、ActionScriptは、インタプリタ型とコンパイル型の中間のプログラミング言語ということになりそうです。とはいえ、仕様はECMAScriptに準拠しています。また、ネット上で実行されるというFlash Playerの性質から、そのプログラムサイズには大きな制約があります。少なくとも現在の段階では、おもに小規模のプログラムを目的とするということができます。したがって、ActionScriptは「スクリプト」であるとして、差支えはないでしょう。

●03 クラス(オブジェクト)について
ActionScriptは、オブジェクト指向プログラミング言語です。その形式的な特徴として、言語がクラスを基本に構築されています。

たとえば、Flashムービーの中で、ムービークリップシンボルのインスタンスは重要な役割を果たします。「ActionScriptリファレンスガイド」を見ると、MovieClipというクラスが存在し、さまざまなプロパティやメソッドが定義されています。ムービークリップインスタンスは、ActionScriptの世界では、MovieClipクラスのインスタンスとして捉えられます。

図001■ステージに配置されたムービークリップシンボルのインスタンス

図002■「ActionScriptリファレンスガイド」の「MovieClipクラス」の項

そこで筆者は、ムービークリップインスタンスを、ActionScript上の存在としてMovieClipインスタンス(あるいは単にMovieClip)と表記しています。同じように、ボタンインスタンスはButtonインスタンス(またはButton)、テキストフィールドはTextFieldインスタンス(またはTextField)と表現します(ただし、[静止テキスト]は、ActionScript上の存在とはいえません)。

ActionScriptは他にも、サウンドをコントロールするSoundクラスや、ムービークリップインスタンスのカラーを変更するColorクラス、外部テキストやXMLドキュメントをロードしたり解析するためのLoadVarsやXMLなどといった、目に見えないクラスも数多く扱います。

Flashのアニメーションでは、シンボルを活用することがひとつのポイントです。タイムラインには[ライブラリ]からシンボルのインスタンスをいくつでも配置でき、インスタンスはそれぞれ個別に設定を変えたり、アニメーションさせることが可能です。

ActionScriptでは、クラスがシンボルと似た重要な役割を果たします。つまり、クラスもインスタンスを作成します。クラスから作成されたインスタンスを、一般に「オブジェクトインスタンス」あるいは単に「インスタンス」と呼びます(MovieClipインスタンスも、ActionScript上はMovieClipクラスのインスタンスです)。そして、それらのインスタンスをActionScriptがコントロールして、インタラクティブなインターフェイスやナビゲーションをつくりあげるのです。

シンボルはインスタンスに対して、タイムラインやビジュアル(視覚)的なデータを提供します。シンボルは、いわばインスタンスのひな形(テンプレート)になる訳です。他方クラスは、そのインスタンスに対してプロパティとメソッドを提供します。クラスもやはり、オブジェクトインスタンスのひな形ということができます。

Advanced Topic□prototype
ひな形は、英語でprototypeといいます(prototypeは、通常は「原型」と訳されます)。ActionScriptでは、すべてのクラスが実際にprototypeというオブジェクトを備えています。そして、クラスのプロパティやメソッドは、そのprototypeオブジェクトに収められています。

オブジェクトインスンタンスは、自分が作成されたクラスのprototypeからそれらのプロパティやメソッドを受継ぐ(「継承」といいます)仕組みになっているのです。prototypeや継承については、「ActionScript 2.0と1.0の継承について」をご参照ください。

●04 オブジェクト・クラス・インスタンス【Advanced】
Flash MXまでの「ActionScriptリファレンスガイド」では、MovieClipの先頭の項目は「MovieClip(オブジェクト)」とされていました。ところが、Flash MX 2004では、「MovieClipクラス」という名称に変わっています。では、オブジェクトとクラスは、同じものなのでしょうか。「オブジェクト」の意味は、オブジェクト指向プログラミングの用語としては、使う人によって少し幅があるようです。そこで、まず「クラス」と「インスタンス」の区別から先に解説しましょう(IT Pro「オブジェクト,クラス,インスタンスの関係」参照)。

前項03では、「クラス」はFlashムービーのシンボルのようなもので、その内容をもとに「インスタンス」を作成するとご説明しました。これで、何となくイメージはできると思います。しかし、もう少し具体的に、ふたつの関係を考えてみます。

「クラス」は概念的・抽象的なもので、「インスタンス」はクラスを実体化・具体化したものだと説明されることがあります。実際、英語のinstanceには「実例」という意味があります。また、「クラス」は、「インスタンス」をつくり出す存在だともいわれます。「クラス」は設計図で、「インスタンス」が製品だと例えられたりもします。

これらの説明の中では、設計図と製品の例えが比較的わかりやすいでしょうか。しかし、まだ身近な感じがしませんので、例えを変えましょう。「クラス」は、料理の「レシピ」です。そのレシピにしたがって、実際につくられるひと皿ひと皿の「料理」が「インスタンス」になります。あたりまえのことですが、「レシピ」は食べられません。料理の素材・味つけ・調理方法を、「定義」したものだからです。これが概念的・抽象的だということの意味です。レシピからつくった具体的な「料理」が、「実体」として口にできるものなのです。

では初めに戻って、「オブジェクト」とは何でしょう。多くの場合、「インスタンス」を指す用語として使われているようです。しかし、「MovieClipオブジェクトには、水平座標のプロパティとして_xがある」というように、個々のインスタンスでなく一般的な説明をする場合には、むしろ「クラス」を意味していると捉えられることも少なくありません。Flash MX以前の「ActionScript辞書」で、「MovieClip(オブジェクト)」というのは、明かに「クラス」を表しています。

考えてみれば、「料理」という言葉も、「オブジェクト」に似たところがあります。テーブルに運ばれてくるひと皿ひと皿が「料理」です。しかし、「フランス料理」や「イタリア料理」という場合には、器に盛られた料理のことではなく、それぞれの国の伝統的な「レシピ」による料理のスタイルという意味になります。

「オブジェクト」という用語も、具体的には文脈から判断すべきことになります。大切なのは、用語に惑わされることなく、「クラス」と「インスタンス」とを理解し、区別することです。

●05 メソッドとプロパティ
クラスは、プロパティとメソッドの定義の集まりです。プロパティは、データあるいは設定値といえます。メソッドは、データの操作・処理手順あるいは命令・コマンドです(英語のmethodには、「手順」「方法」という意味があります)。

クラスからインスタンスを作成すると、定義されたプロパティに値を設定したり、メソッドで操作をすることが可能です。つまり、インスタンスには、そのクラスのプロパティやメソッド一式が自動的にパッケージされてついてくるのです。これが、オブジェクト指向プログラミング言語の特徴です。

すると、クラス(オブジェクト)の種類によって、設定できるプロパティや実行できるメソッドが決まってくることになります。MovieClipインスタンスの水平座標は、_xプロパティによって設定することが可能です。他方、ButtonインスタンスやTextFieldインスタンスの水平座標も、_xプロパティで変えられます。しかし、Flash 5では、ButtonやTextFieldの位置をActionScriptで制御することができませんでした。これは、Flash 5には、ButtonやTextFieldというクラス(オブジェクト)が定義されていないからです。クラスがなければ、当然プロパティも存在しません。ですから、制御は不可能だということになるのです。

「ActionScriptリファレンスガイド」にはMovieClip._xプロパティが存在し、その解説があります。同様に、Flash MX以降では、Button._xTextField._xプロパティも掲載されています。つまり、たまたま(というよりわざわざ)同じ名前の_xというプロパティが定義されているものの、それぞれは異なるクラスの別個のプロパティだということです。

ActionScriptは、基本的にインスタンスを操作して、ムービーをコントロールします。オブジェクトインスタンスの代表は、もちろんMovieClipです。その他、ButtonやTextFieldなどステージ上に表示されているものから、SoundやXMLなどの目に見えないインスタンスも存在します。インスタンスは、プロパティとメソッドによって操作します。

ですから、ActionScriptでムービーをコントロールするには、まず操作の対象となるオブジェクト(クラスとそのインスタンス)を特定します。つぎに、そのクラスのプロパティやメソッドを探します。そして、そのインスタンスに対して、目的に応じたプロパティあるいはメソッドを操作します。

表001■ActionScriptでムービーを操作するには
手順 内容

[1]対象
[2]手段
[3]実行

操作対象のインスタンスとそのクラスを特定する
操作すべきプロパティやメソッドを探す
インスタンスに対してプロパティあるいはメソッドを操作する

Advanced Topic□インスタンス名とその参照
ActionScriptでムービーを操作するための上記のステップは、わざわざ説明する必要がないように思われるかもしれません。しかし、スクリプトをある程度わかっている人でも、つぎのような間違いを犯すことがあります。タイムラインには、MovieClipインスタンスmy_mcが配置してあるとします。

スクリプト001■インスタンス名からMovieClipに対する間違ったアクセス

// _rootフレームアクション
myName = "my_mc";
trace(myName); // 出力: my_mc
trace(typeof myName); // 出力: string
myName._x = 100;

myNameは、MovieClipインスタンスではなく、その名前の文字列(ストリング)です。typeof演算子は、データのタイプを(ストリングで)返します。"string"という出力結果は、myNameの値が文字列であることを示します。文字列(Stringクラス)には、_xプロパティが存在しません。したがって、上記のスクリプトでは、インスタンスmy_mcの水平座標(_x)を操作することができません。

インスタンス名の文字列を、ターゲットパス(参照)に変換するには、eval()関数を使います(配列アクセス演算子[]を使用することもできます)。以下のスクリプトは、「文字列」をインスタンスへの「参照」に変換しているので、my_mcの水平座標を100ピクセルの位置に設定することができます。

スクリプト001■インスタンス名からMovieClipに対する正しいアクセス

// _rootフレームアクション
myName = eval("my_mc");
// myName = this[my_mc];   // 配列アクセスによる場合
trace(myName); // 出力: _level0.my_mc
trace(typeof myName); // 出力: movieclip
myName._x = 100;

クラスとかプロパティやメソッドというと、抽象的でピンとこないかもしれません。そういう人は、身の周りにある家電やAV機器で考えてみるとよいでしょう。たとえば、TVがオブジェクトです。プロパティには、選択されたチャンネルやボリューム、画面の明るさやコントラスト、色合いといった設定があります。TVのリモコンやコントロールパネルにあるボタンで、それらの設定を変更することができます。ですから、これらのボタンが、メソッドに当ります(正確には、ボタンで操作される電気回路といった方がよいでしょう)。

TVをつけるには、リモコンを取って「電源」とか「Power」という表示のあるボタンを押します。すると、なぜかビデオデッキの電源が入ってしまったという経験はありませんか? リモコンを取違えたということです。電源ボタンはどのリモコンにもありますが、TVを見たいのであれば、TVのリモコンを手にしないといけません。つまり、まず操作対象の家電を特定し、そのリモコンを手に取ります。つぎに、操作すべき手段となるメソッドつまり電源のボタンを探します。そして、リモコンをその家電に向けてボタンを押すという操作を実行すれば、晴れてTVが映るということです。

ActionScriptのほとんどの操作の基本単位は、クラスとインスンタンスです。ですから、「ActionScriptリファレンスガイド」も、クラスごとにプロパティとインスタンスの説明をまとめています。したがって、スクリプトを書くには、どのオブジェクト(インスタンス)を操作するのかということからスタートする必要があるのです。

●06 ActionScript 2.0とFlash Player 7【Advanced】
Flash MX 2004から、ActionScript 2.0が実装されました。Flash MXまでのActionScriptは、バージョンが1.0ということになります。もっとも、Flash MX 2004でも、ActionScript 1.0を使用することは可能です。ActionScript 2.0は、新たなシンタックスを採用し、デバッグの機能も拡充されています。

ActionScript 2.0の仕様も、やはりECMA-262によって定められています。ただし、ActionScript 1.0がECMA-262第3版に準拠するのに対して、ActionScript 2.0は第4版にもとづきます。

Word□ECMA-262第3版と第4版
ECMA-262第3版は、「Standard Ecma-262 ECMAScript Language Specification 3rd edition」(1999年12月)という文書により規定されました。「01 ECMAScriptとしてのActionScript」に述べたとおり、JavaScriptやJScriptが、この標準に準拠しています。

これに対して、ECMA-262第4版は、「ECMAScript 4 Netscape Proposal」という提案書にもとづく仕様です。ECMA-262第4版に準拠する言語としては、JavaScript 2.0JScript.NETが挙げられます。

ECMA-262第4版に準拠するActionScript 2.0は、厳密な型指定とクラスをベースとしたプログラミングスタイルに大きな特徴があります。ActionScript 2.0について詳しくは、「ActionScript 2.0を使ったクラスの作成概要」および本サイトのActionScript 2.0に関するノートをご参照ください。。

Word□型指定
変数、あるいは関数の引数や戻り値に、データ型を指定できる機能です。「型」というのは、そのデータの属するクラスを意味します。指定した型と異なるデータを設定しようとすると、Flash MX 2004はコンパイル(SWF書出し)時にエラーを発生します。そのため、意図しないデータを、変数や関数に設定するミスが防げます。

ActionScript 2.0を使用した場合、Flash Player 7はもちろん、Flash Player 6でパブリッシュすることも可能です。これは、Flash MX 2004の現状では、後述(「07 ActionScript 1.0 vs 2.0」)のとおり書出されるバイトコードが1.0と基本的には異ならないからです。ActionScript 2.0を使ったFlash Player 6書出しについては、「ActionScript 2.0と1.0の継承について」の「3. ActionScript 2.0の継承をFlash Player 6で書出した場合」をご参照ください。

ActionScript 2.0の採用とは別に、Flash Player 7ではECMA-262への準拠を強めています。そのため、Flash Player 6以前と仕様が一部変わりました。これは、ActionScript 1.0でスクリプトを記述したとしても、Flash Player 7でパブリッシュを行った場合、バージョン6以前とは動作が違ってしまう可能性のあることを意味します。とくに、旧バージョンで作成したムービーをFlash MX 2004で修正・変更して、Flash Player 7で書出す場合に注意が必要です。パブリッシュで、Flash Player 7を指定するか、それより前のバージョンを選択するかによって、動作が異なる部分はつぎの表002のとおりです。

表002■Flash Player 7と6以前のバージョンとの違い
相違点 Flash Player 7にパブリッシュしたSWF 6以前のバージョンのFlash PlayerにパブリッシュしたSWF
大文字小文字の区別 大文字小文字だけが異なる同一の変数名(識別子)は、別個に解釈されます。アクションの多くは、大文字小文字を正確に記述しないと、動作しません。この仕様は、#includeで読込む外部ActionScriptファイル内のスクリプトや、外部ファイルからロードした変数名にも適用されます。 大文字小文字が異なっても、同一の変数名(識別子)は同じものとして解釈されます。
未定義値undefinedを数値として評価したとき 未定義値undefinedは、NaNに変換されます。未定義の変数に数値演算を繰返しても、結果はつねにNaNになります。 未定義値undefinedは、数値0に変換されます。
未定義値undefinedをストリングとして扱ったとき 未定義値undefinedは、ストリングの"undefined"に変換されます。 未定義値undefiendは、空文字列""に変換されます。
ストリングをプール(論理)値として評価したとき ストリングの長さ(String.lengthプロパティの値)が0より大きければtrueに、空文字列(長さ0)ならfalseに変換されます。 ストリングはまず数値として評価されます。その結果が数値0であれば、ブール(論理)値trueに変換されます。それ以外は、(数値として評価できない場合も含めて)falseとされます。
配列に対する値の設定と配列の長さ インデックスとして有効な0以上の整数を指定した場合にのみ、配列の長さArray.lengthプロパティの値が変更されます。 完全な数字でなく、スペースや文字の含まれたプロパティを設定した場合にも、配列の長さArray.lengthプロパティの値は変更されることがあります。

[1] 大文字小文字の区別
Flash Player 7書出しでは、変数や関数、プロパティ、メソッドなどの名前(「識別子」といいます)について、英字の大文字と小文字が区別されます。したがって、変数myVariableとmyvariable、MYVARIABLEは、すべて別個ものとして扱われます。また、_root.Stop()と記述しても、メインタイムラインは停止しません(正しくは、_root.stop())。

Word□識別子(identifier)
インスタンスや変数、関数(function)などに設定して、プログラムで制御するために用いる名前です。

(1) 使える文字は、半角英数字、または記号は「_」(アンダースコア)と「$」(ドル記号)のみです。
(2) 先頭に数字を用いることはできません。
(3) 大文字小文字は、Flash Player 7以降は区別されます(Flash Player 6以前は区別が推奨されます)。

また、ActionScriptのキーワード・予約語と重複しないことが前提とされます。なお、Flash MX 2004オンラインヘルプ[ActionScriptユーザーガイド] > [ActionScriptの基礎] > [用語]をご参照ください。

Flash Player 6以前の形式では、大文字と小文字が区別されません。しかし、同一の名前(識別子)を表記するのに、大文字小文字を統一して使用しないと、プログラムのミスを招きやすくなります。ですから、Flash Playerのバージョンにかかわらず、大文字と小文字は区別して使うべきでしょう。

[2] 未定義値undefinedを数値として評価したとき
未定義値undefinedを扱った処理には、注意が必要です。Flash Player 6までは、未定義値undefinedを数値として演算の対象にすると、値は0に変換されました。ですから、つぎのような加算の処理で、数値のカウントアップが可能でした(スクリプト002)。

Word□undefined
未定義値を示す特別な値です。値を設定する前の変数値や、デフォルト値の設定されていないプロパティの値を参照すると返されます。typeof演算子で調べると、ストリングの"undefined"を返します。

スクリプト002■Flash Player 6以前でundefinedに数値を加算
// Flash Player 6以前
// myCountは未定義の変数です
myCount += 1;
trace(myCount); // 出力: 1

上記のスクリプトを繰返し実行すれば、整数値が加算されていきました。しかし、Flash Player 7からは、未定義値undefinedを数値演算の対象とすると、NaNに変換されます(スクリプト003)。

スクリプト003■Flash Player 7でundefinedに数値を加算

// Flash Player 7
// myCountは未定義の変数です
myCount += 1;
trace(myCount); // 出力: NaN

NaNに対しては、どのような数値演算を行っても、結果はNaNのままです。したがって、Flash Player 7でこのスクリプトを繰返し実行しても、結果はつねにNaNになります。

Word□NaN
数値演算やデータ型の変換を行ったときに、数値として表せない結果になったとき返される特別な値です。NaNという名前は、非数値(Not a Number)からきています。たとえば、0を0で除算した場合が、これに当たります。0による除算は、未定義なためです(0でない値を0で除算することも、数学の演算上は未定義です。しかし、ActionScriptでは除される値が正の場合はInfinity、負の場合には-Infinityを返します)。

NaNを数値演算の対象にすると、結果はつねにNaNになります。ただし、typeof演算子でデータ型を調べると、"number"つまり数値型です。したがって、「非数値」というよりは、「数値演算不能値」と理解する方がよさそうです。

[3] 未定義値undefinedをストリングとして扱ったとき
未定義値undefinedをストリング(文字列)として処理する場合も、Flash Player 7と6以前とでは結果が異なります。Flash Player 6までは、未定義値を文字列として扱うと、空文字列""に変換されます。ですから、未定義の変数に演算子+でストリングを連結すると、変数を処理に加えなかったのと同じ結果になります(スクリプト004)。

スクリプト004■Flash Player 6以前でundefinedに文字列を連結

// Flash Player 6以前
// middleName_strは未定義の変数です
myName_str = "Fumio "+middleName_str+"Nonaka";
trace(myName_str); // 出力: Fumio Nonaka

しかし、Flash Player 7からは、未定義値undefinedがストリングの"undefined"に変換されます。したがって、同じスクリプトの結果が、つぎのように変わります(スクリプト005)。

スクリプト005■Flash Player 7でundefinedに文字列を連結

// Flash Player 7
// middleName_strは未定義の変数です
myName_str = "Fumio "+middleName_str+"Nonaka";
trace(myName_str); // 出力: Fumio undefinedNonaka


Advanced Topic□未定義値をストリング"undefined"に変換する意味
未定義値undefinedをストリングの"undefined"に変換したのでは、何の役に立つのかわらないかもしれません。しかし、値をストリングに変換する処理は、さまざまな場面で求められます。たとえば、配列の値をtrace()アクションで出力するとき、各エレメントはストリングに変換されます。

スクリプト006■配列中の未定義エレメントをtrace()ステートメントで出力

// Flash Player 7
// 変数aは未定義です
b = 1;
my_array = [a, b];
trace(my_array); // 出力: undefined,1

Flash Player 6以前では「,1」と出力されるので、変数aの値が空文字列""なのか未定義値undefinedなのかの区別がつきません

[2][3]の未定義値undefinedの処理を、バージョンにかかわらず統一的に扱えるようにするためには、変数には必ず初期値を与えるのがよいでしょう(スクリプト007および008)。変数を宣言するvarステートメントを用いると、変数の初期値を設定していることが明確になります(var宣言をしなくても、処理結果は同じになります。varステートメントについては、「ActionScriptリファレンスガイド」をご参照ください)。

スクリプト007■変数を宣言して数値の初期値を与える

// 変数の初期化
var myCount = 0;
// Flash Playerのバージョンにかかわらず同一の処理
myCount += 1;
trace(myCount); // 出力: 1


スクリプト008■変数を宣言して文字列の初期値を与える

// 変数の初期化
var middleName_str = "";
// Flash Playerのバージョンにかかわらず同一の処理
myName_str = "Fumio "+middleName_str+"Nonaka";
trace(myName_str); // 出力: Fumio Nonaka

[4] ストリングをプール(論理)値として評価したとき
ストリングを直接if条件に設定するなど、ブール(論理)値として評価する場合も、Flash Player 7とそれより前とでは処理が異なります。Flash Player 7では、ストリングが空("")でなければ、trueとして扱われます。具体的には、ストリングの長さ(String.lengthプロパティの値)が調べられ、0ならfalse、0より大きければtrueに変換されます。

Flash Player 6の処理は、少し変わっています。ストリングは、まず数値として評価され、その結果0以外の数値ならtrueとして扱われます。そして、それ以外の場合つまり、数値0と評価されるか、数値として扱えない(NaNの)場合をfalseとします。

Advanced Topic□ストリングの入力を確認する
Flash Player 7の新しい仕様は、ストリングの入力チェックを行う場合に都合がよいです。ユーザーに[テキスト入力]TextFieldへの入力を求め、何かしら文字がタイプされたかどうか確認するには、つぎのスクリプトで足ります(スクリプト009)。TextFieldインスタンスmy_txtは、スクリプトを記述したタイムラインに配置されているものとします。

スクリプト009■ストリングが空文字列""でないかを調べる

if (!my_txt.text) {
  trace("No entry!");
}

TextField.textプロパティは、値がストリングです。値が設定されていない場合には、空文字列""を返します。その値を直接if条件に指定すると、空文字列("")の場合にfalseと評価されますので、否定演算子!により逆に未入力のときtrueになります。


Advanced Topic□未定義値undefinedの扱い
未定義値undefinedが、数値コンテクストで0([2])、文字列コンテクストで空文字列""([3])、ブール(論理)値として評価する場合には一旦数値に変換される([4])というのは、ECMA-262第3版仕様と異なっていました。これは、ActionScriptが実装されたFlash 5より前のバージョンと、互換性を取るための仕様だったものと思われます。もちろん、Flash MX 2004でも、Flash Player 6以前のフォーマットで書出せば、この仕様が維持されます。

[5] 配列に対する値の設定と配列の長さ
配列Arrayクラスのオブジェクトは、通常整数インデックスで配列エレメント(要素)を管理します。しかし、他方で他のクラスのオブジェクトインスタンスと同様に、プロパティを設定することも可能です。配列の長さを示すArray.lengthプロパティは、本来整数インデックスで管理されたエレメントのみを対象とします。

ところが、Flash 5およびMXでは、数値ではじまるプロパティ名や数値の前に半角スペースを加えたプロパティを設定しても、その数値を元にArray.lengthプロパティの値が更新されてしまいました(表003)。

表003■数値ではじまる配列エレメントと配列の長さ
Flash Player 7にパブリッシュしたSWF 6以前のバージョンのFlash PlayerにパブリッシュしたSWF
my_array = new Array();
my_array[1] = 1;
trace(my_array.length); // 出力: 2
my_array[" 2"] = 2;
trace(my_array.length); // 出力: 2
my_array[" 3a"] = 3;
trace(my_array.length); // 出力: 2
my_array["4xyz"] = 4;
trace(my_array.length); // 出力: 2
trace(my_array); // 出力: undefined,1
my_array = new Array();
my_array[1] = 1;
trace(my_array.length); // 出力: 2
my_array[" 2"] = 2;
trace(my_array.length); // 出力: 3
my_array[" 3a"] = 3;
trace(my_array.length); // 出力: 4
my_array["4xyz"] = 4;
trace(my_array.length); // 出力: 5
trace(my_array); // 出力: ,1,,,

配列のArrayクラスは、Flash 5から実装されたもので、それより前のバージョンとの整合性が問題になることはありません。また、配列の長さが変わっているにもかかわらず、配列そのものをtrace()アクションで出力したとき、配列エレメントとしては扱われていない(my_array.lengthが5で、出力が「,1,,,」となっている)ことから考えても、Flash Player 6以前の結果は整合性を欠くといわざるをえません。

この仕様変更は、バグ修正と見るべきでしょう(ただし、過去のコンテンツの動作を変えないという意味で、上位互換性が保たれています)。

Advanced Topic□識別子でないプロパティ
オブジェクトのプロパティ名には、一般に「識別子」を用います。識別子は、先頭を数字にすることはできませんし、(半角)スペースを使うことも禁じられます。したがって、表003の例のようなプロパティ名を設定することは、避けた方がよいでしょう。

実際、識別子以外のプロパティ名を使うと、通常ドットシンタックスでアクセスすることができず、エラーになります。ただ、配列アクセス演算子[]を使って値を調べることは可能です。

スクリプト010■設定したプロパティに配列アクセス演算子でアクセス
// 表003のサンプルスクリプトを実行した場合
trace(my_array[" 2"]); // 出力: 2
trace(my_array[" 3a"]); // 出力: 3
trace(my_array["4xyz"]); // 出力: 4

Advanced Topic□Flash Playerの最適化
Flash Player 7では、スクリプトの処理速度が向上しています。なかでも、「レジスタ」というCPUの処理データを格納するアクセスの極めて速いメモリが、関数の呼出しにともなって最大256個使用できるようになった点は大きいでしょう。レジスタは、関数のローカル変数を扱う際に活用されます。Flash Plyaer 6以前はその数が4個しかなく、スクリプトで実際に使用できるのはたったひとつだったといわれます。

「Macromedia Flash (SWF) File Format Specification Version 7」(ライセンス契約に同意後PDFをダウンロードできます)には、Flash Player 7で関数を扱う新しいバイトコード「ActionDefineFunction2」について、つぎのように説明されています(p.87。またp.15も併せて参照)。

"ActionDefineFunction2 is similar to ActionDefineFunction, with additional features that can help speed up the execution of function calls by preventing the creation of unused variables in the function's activation object and by enabling the replacement of local variables with a variable number of registers. With ActionDefineFunction2, a function may allocate its own private set of up to 256 registers. (The activation object is an implicit local scope that contains named arguments and local variables. See the ECMA-262 standard for further description of the activation object.)"

なお、Flash Player 6書出しでも、[パブリッシュ設定]の[Flash]タブで[Flash Player 6r65用に最適化]オプションをチェックする(図003)と、レジスタを用いた処理の最適化(ActionDefineFunction2のサポート)が適用されます(前掲p.88参照)。

図003■[パブリッシュ設定]の[Flash Player 6r65用に最適化]オプション

●07 ActionScript 1.0 vs 2.0
ActionScript 2.0は、クラスベースのプログラミングスタイルが最大のポイントです。もうひとつの特徴である厳密な型指定も、クラス定義において重要な意味をもちます。もっとも、クラスベースの開発が必要とされるのは、スクリプトとコンテンツデザインの担当者が分担して協同する規模の大きなプロジェクトだと思われます。

他方、比較的小規模で、スクリプティングとデザインとを明確に分けないプロジェクトもあります。こうしたコンテンツでは、従来のFlashと同じフレームやMovieClipインスタンスなどのタイムライン(MovieClip)に記述するスクリプトの方が、小回りも利いて便利な面も少なくないでしょう。おそらくコンテンツの数でいえば大多数を占めると思われるこのような小規模のムービーでは、引続きActionScript 1.0を使用して問題ありません。

実際、型指定をしなければ、(クラス定義をしない)通常のフレームアクションやMovieClipアクションでは、ActionScript 2.0と1.0の違いはありません。そして、Flash MX 2004のスクリプティングにおいても、型指定は必須という訳ではないのです。むしろクラス定義以外では、型指定をあえてすべき場合は多くはないでしょう。

また、型指定はFlashがコンパイル(SWF書出し)するときのみのチェックです。つまり、書出されたSWFには、型指定の情報が残りません。その意味では、一種のシンタックスチェックにすぎないと見ることもできます。さらに、ActionScript 2.0でスクリプトを記述しても、SWFに書出されるバイトコードは、Flash MX 2004ではActionScript 1.0とほとんど異なるところがありません(将来のバージョンで、ActionScript 2.0に最適化された実装がなされる可能性はあります)。

_____

作成者: 野中文雄
作成日: 2005年6月22日


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