スコープが定められた新たな関数を返す。スコープ(this参照)を定める関数。関数内のスコープ(this参照)として定めるオブジェクト。呼出した関数に渡したい引数があれば、任意の数加えられる(オプション)。定められたオブジェクトを関数内のスコープ(this参照)とした新たな関数。説明proxy()はCreateJSにグローバルに定められた関数で、オブジェクトもクラスも参照せず、名前空間(createjs)に続けて直接呼出します。SoundJSとPreloadJSのふたつのライブラリに、JavaScript(JS)ファイルProxy.jsとして加えられています。それぞれのコンパクト(min)版JSファイルにも含まれます。JavaScriptでは、関数もプロパティに含まれます。オブジェクトのプロパティに加えた関数は、そのオブジェクトのメソッドとみなされます。オブジェクトに与えた関数を呼出すと、関数本体のthisキーワードはそのオブジェクトを参照します。関数が定められたスコープは保たれないのです。CreateJSのproxy()関数は、第1引数の関数に第2引数のスコープを定めた新たな関数を返します。戻り値の関数は、どのオブジェクトのもとで呼出されても、予め定めたスコープが関数本体のthis参照となります。スコープ)たとえば、つぎのJavaScriptコードは、関数(method())をオブジェクト(instance)に定めました。すると、同じ関数を直に呼んだときと、オブジェクトのメソッドとして呼出したときとでは、thisの参照が異なることになります(図001)。this.variable;}図001■関数を直に呼んだときとオブジェクトのメソッドとして呼出したときとではthis参照が変わるproxy()関数を使うと、第1引数の関数をつねに第2引数のスコープで呼出すことができます。戻り値の関数はどのオブジェクトのメソッドに与えても、proxy()関数の第2引数で決めたオブジェクトがthis参照されて呼出されます。0.5.0を読込みました[*1]。オブジェクト(instance)のメソッド(method)に、proxy()関数でスクリプトの記述場所(this)をスコープに定めた関数が与えられました。そのため、オブジェクトのメソッドとして呼んでも、直に呼出しても、this参照は変わりません(図002)[*2]。this.variable;}</script>図002■関数を直に呼んでもオブジェクトのメソッドとして呼出してもthis参照は変わらないproxy()関数に渡した第3引数以降は、戻り値の関数を呼出したときその引数に加えられます。つぎのようにオブジェクト(myObject)のイベント("event")にリスナーとしてproxy()関数の戻り値を加えると、イベントが起こったときに第3引数以降(arg1とarg2)をリスナー関数は引数として受取ります。リスナー関数が呼出されるとき引数として渡されるイベントオブジェクト(eventObject)の後に加わります[*3]。イベント"event"でリスナー関数として呼出される}proxy()関数の戻り値となる関数は、第1引数の関数にもとづいて新たにつくり直されます。第1引数の参照とは異なる関数です。そのため、proxy()関数で定めたリスナーを削除するには、その参照を得なければなりません。EventDispatcher.addEventListener()メソッドは加えたリスナーの参照を返すので、それをもっておけばよいでしょう。0.4.0にもproxy()関数は備わっています。0.5.0とは異なってSoundクラスの中で定められていたり、「CreateJSのproxy()メソッドに第3引数が渡せない」という問題がありました。本文の例では、関数内でthisキーワードを使わなければ、いずれもグローバルに定めた変数が参照されます。global,global}ただし、同じ名前のローカル変数があると、その値が参照されてしまいます。この場合、グローバルな変数の値を得るには、参照先を定めなければなりません。Documentation」のproxy()メソッドの項で「Example」に掲げられた例は、リスナー関数(myHandler())の引数にイベントオブジェクトが定められていません(図003)。この場合、第1引数はイベントオブジェクトを受取り、proxy()メソッドで与えたふたつの引数の2番目が受取れません。例HTMLドキュメントに加えたボタンで、サウンドの停止と再生をしてみましょう(図004)。以下のコードのように、ボタンはbody要素にinput要素で加え、type属性を"button"に定めます。JavaScriptで参照を得るため、id属性に識別子("control")を与えておきます。/></body>script要素としては、以下のコード001を書き加えます。ひとつのボタンで、停止と再生を切替えます。それぞれの設定は、ふたつの関数(readyToStop()とreadyToPlay())で定めました。どちらも、サウンドを操作してボタンクリックのハンドラを切替えるため、引数にSoundInstanceオブジェクトとボタンのふたつの参照が求められます(第16および第23行目)。サウンドが再生し終わったときのSoundInstance.completeイベントには、proxy()関数で第1引数の関数(soundCompleted())のスコープを第2引数のボタン(control)にしてリスナーに定めました(第8〜9行目)。リスナー関数(soundCompleted())からは、ボタンの設定を再生にする関数(readyToPlay())を呼出します(第14行目)。このとき、SoundInstanceオブジェクトの参照は、引数に受取ったイベントオブジェクト(eventObject)のtargetプロパティから得られます(第13行目)。proxy()関数によりthis参照がボタンになっていますので、関数に渡すふたつの引数が揃います。このようにして、SoundInstanceオブジェクトとボタンのどちらの参照もグローバルな変数に定めることなく、サウンドの停止と再生のコントロールが行われるのです。"stop";}</script>以下のコード002は、オブジェクトにふたつのメソッドを加えます。proxy()関数により、そのスコープは別のオブジェクトに定めます。そのうえで、ふたつのメソッドを呼出して、それぞれのthis参照がどう変わったか確かめます。ふたつのオブジェクト(pointとtemplate)には、xy座標を想定したプロパティ(xとy)が加えられています(第4〜5行目)。そのうちのひとつのオブジェクト(template)に、メソッドをふたつ(transfer()とtoString())与えます。proxy()関数で、それらのスコープはもうひとつのオブジェクト(point)に定めました(第6〜7行目)。0)に対して伸縮・回転します。第1引数(scale)が伸縮比率、第2引数を回転角(rotation)として、関数(transfer())で座標変換します(第10〜20行目)。60)で呼出します(第8行目)。オブジェクト(template)のふたつ目のメソッド(toString())には、EaselJSのPoint.toString()メソッドを譲受けました(第7行目)。オブジェクトは文字列表現が求められると、内部的にそのtoString()メソッドを呼出して戻り値の文字列が用いられます。配列がWindow.alert()メソッドで警告ダイアログに表示されるとき、それぞれの配列エレメントは文字列に変換されます(第9行目)。Point.toString()メソッドは、つぎのような文字列を返します。y=yプロパティ値)]オブジェクト(template)のメソッドふたつ(transfer()とtoString())は別のオブジェクト(point)をスコープに定めたので、メソッドで操作されるのはスコープのオブジェクトで、呼出したオブジェクトは何も変わりません。y;}</script>警告ダイアログボックスには、結果を納めた配列がつぎのように示されます(図005)。初めのふたつのエレメントは、メソッドを与えたオブジェクト(template)のxy座標のプロパティ値です。0)から変わっていません。y=1.7320508075688772)]配列の3つ目のエレメントには、オブジェクト(template)そのものが納められています。すると、前述のとおり、エレメントであるオブジェクトの文字列表現(toString()メソッドの戻り値)が示されます。√3)になっています(実際には、わずかな誤差が含まれます)。図005■警告ダイアログボックスにふたつのオブジェクトの情報が示されたご参考までに、座標変換の関数(transfer())について、簡単に解説を加えます(この処理内容はproxy()関数には関わりません)。関数がオブジェクトのメソッドとして呼出される前提とします。前述のとおり、座標変換の関数(transfer())は、第1引数(scale)が伸縮率、第2引数(rotation)は回転角です(第10行目)。オブジェクトの座標プロパティ値を変数(xとy)にとります(第11〜12行目)。メソッドが受取る第1引数の伸縮率は、ふたつのプロパティ値に乗じます(第16〜17行目)。つぎに、メソッドの第2引数(rotation)にもとづく角度(θ)の回転は、以下の計算式でxy座標を変換します(詳しくは「三角関数で座標を回転するふたつの計算方法」をお読みください)。三角関数は角度にラジアンを用いるため、定数Matrix2D.DEG_TO_RADで予め度数から変換しています(第13行目)。三角関数の値は予め変数(sinとcos)に与えます(第14〜15行目)。上記の式で求めた値を、オブジェクトに新たなプロパティ値として定めています(第18〜19行目)。これで、オブジェクトの座標が、原点から伸縮および回転されます。実装CreateJSの関数proxy()は、Soundクラスの中でつぎのコード003のように実装されています。用いられているおもなメソッドとともに、以下にかいつまんでご説明します(抜書きする行番号はコード003にもとづきます)。0).concat(aArgs));};}●proxy()関数は関数を返すproxy()関数はつぎのように、returnステートメントで名前のない関数(function)をつくって返します(第3〜5行目)。この戻り値の関数が、proxy()関数の第1引数の関数(method)を第2引数のスコープ(scope)で呼出す新しい関数です。したがって、その新たな関数は、メソッド(method)をスコープ(scope)で呼出し、その結果を返すということになります(第4行目)。*/;};}●Functionクラスのスコープを変えるメソッド関数のスコープを変えて呼出すメソッドが、Functionクラスに備わっています。それが、Function.apply()メソッドです。関数(Functionオブジェクト)を参照して呼出します。第1引数はスコープ、第2引数には関数に渡す引数を配列で定めます。関数に渡す引数の配列)proxy()関数の戻り値である新たな関数は、Function.apply()メソッドにより、proxy()関数の第1引数の関数(method)を第2引数のスコープ(scope)で呼出して返しています(第4行目)。*/);Function.apply()メソッドの第2引数には、参照する関数に渡す引数を配列に入れて渡します。proxy()関数の他の処理は、おもにこの引数に渡す配列をつくっています。Functionクラスには、関数のスコープを変えて呼出すもうひとつのメソッドFunction.call()があります。Function.apply()メソッドとの違いは、参照もとの関数に渡す引数をひとつの配列ではなく、その数だけ第2引数以降に定めることです。...)proxy()関数の第1引数に受取る関数は、いくつの引数が渡されるのか予め決まっていません。このような場合は、Function.apply()メソッドを用いると、引数がいくつあってもひとつの配列に納めて渡せます。●argumentsオブジェクトをArrayクラスのメソッドで扱うargumentsは関数が自動的につくるローカル変数です。配列に似たオブジェクトが与えられ、関数の受取った引数を連番インデックスのエレメントとしてもちます。argumentsオブジェクトには配列のメソッドが備わっていません。配列のメソッドが使いたいときには、Function.call()メソッドにより、Arrayクラスのメソッドをargumentsオブジェクトのスコープで呼出します。一般に、クラスに備わるメソッドを参照するときには、クラスのFunction.prototypeプロパティからメソッドを得ます。...)proxy()関数では、まずargumentsオブジェクトに対してArray.slice()メソッドを呼出しています(第2行目)。このメソッドは、配列インデックスの始まりと終わりの整数をふたつ引数に渡すと、その範囲のエレメントが納められた新たな配列を返します。argumentsオブジェクトの第2インデックスは、関数が受取る第3引数です。proxy()関数には第2引数までしか定められていません。argumentsオブジェクトは、関数に定めがなくても、呼出されたとき受取った引数すべてをエレメントに納めます。Array.slice()メソッドの第2引数に終わりのインデックスを渡さないと、始まりに定めた第1引数のインデックスから最後までのエレメントが取出されます。argumentsオブジェクトに第3引数以降が渡されれば、そのすべてを新たな配列として変数(aArgs)に納めます。2);}proxy()関数が返す新たな関数は、その戻り値でFunction.apply()メソッドを呼出していました(第4行目)。そのFunction.apply()メソッドに渡す第2引数の配列が、つぎのようにargumentsオブジェクトをもとにつくられています。このargumentsオブジェクトは、proxy()関数ではなく、メソッドが返す新たな関数が受取ることにご注意ください。argumentsオブジェクトのスコープでArray.slice()メソッドを呼出す処理は、すでにご説明しました。ここでは始まりインデックスに0を渡しています。argumentsオブジェクトのエレメントすべてをそっくりそのままということで、意味がないように感じられるかもしれません。返されるのは新たな配列なので、Arrayクラスのメソッドが使えるようになるのです[*4]。そこで、Array.concat()メソッドを呼出して、proxy()関数が受取った第3引数以降(aArgs)を加えています。0).concat(aArgs)このようにしてproxy()関数から、第1引数の関数を第2引数のスコープで呼出す新たな関数が返されるのです。新たな関数には、もとの関数に定められた引数に加え、proxy()関数に与えた第3引数以降が渡されます。Array.slice()メソッドの第1引数も省くと、始まりのインデックスは0とみなされます。したがって、Function.apply()メソッドに第2引数を渡さなくても構いません(MDN「arguments」「説明」参照)。proxy()メソッド」から変更。CreateJSの新バージョンにもとづいて、全体にわたり加筆・補正した。