• Feb
  • 16
  • 2008

AS3: 「... (rest)」で受け取ったパラメータを他の関数にそのまま渡す

せっかくSyntaxHighlighterをいれたので、スクリプトネタを一つ。

ActionScript 3 になって ... (rest)パラメータというのが追加された。
(argumentsオブジェクトみたいなものだけれど、calleeとcallerがなかったりする)

関数が任意の数の引数を取るような場合、argumetnsオブジェクトを使ったり、この... (rest)パラメータを使う。AS3では、... (rest)を使うように推奨されている。

で、ある関数で受け取った ... (rest) パラメータを別の関数にそのまま渡したいときがあるが、そこでつまずいた。調べてみると、かなり常識的なパターンらしく、とくに解説もないまま方々で使われてた。うーむ。

さて、まず ... (rest) の使い方は、

myMethod( 1, 2, 3 );
 
function myMethod( ... args ):void
{
    trace( args.length ); // 出力: 3
    trace( args ); // 出力: 1, 2, 3
}

という感じだ。argumetnsオブジェクトと基本的には変わらない。

で、この「... (rest)」で受け取ったパラメータをそのまま他の関数に渡す。
(argumentsオブジェクトを使っても同じことらしいが、今まで困ったことはない。さすが非プログラマ)

今回の場合、具体的には ... (rest) で受け取った値をArray.push()に渡したかったんだけれど、引数で受け取った値をArray.push()に渡すときに、Function.apply()を使えば良かったらしい。

var itemArray:Array = new Array();
 
addSomeItem( "item1", "item2", "item3" );
 
//配列のエレメントを出力
for( var key in itemArray )
{
    trace( "item[" + key + "] = " + itemArray[key] );
}
 
//配列にアイテムを追加
function addSomeItem( ... someItems ):void
{
    itemArray.push( someItems ); //失敗
    itemArray.push.apply( itemArray, someItems ); //成功
}
 
// 出力結果:
// item[0] = item1,item2,item3
// item[1] = item1
// item[2] = item2
// item[3] = item3

こんな感じ。

Array.push()は引数に任意の数のパラメータを取るので、複数のパラメータを指定すれば、配列には複数のエレメントが追加される。

ここで、Array.push()に ... (rest) のパラメータの配列名 restを直接渡してしまうと、配列のエレメントには配列が追加されてしまい、上記出力結果の「item[0]」のようになる。

これを回避するのに Function.apply() を使うのだが、Function.apply() では呼び出す関数に渡す引数に配列を指定する。この配列はカンマ区切りのパラメータとして関数に渡される(らしい)ので、この特徴を利用して期待通りの動作が実現できる、というカラクリだ。

なお、Function.apply() の一つ目の引数は、呼び出す関数内でthisが参照する場所を指定するのに使うらしいが、ここではpushを呼び出している配列「itemArray」で良いと思う。とくにthisを気にしなくていい場合はnullを指定すれば良い。

Function.call() という似たようなメソッドもあるけれど、こちらは引数を配列でなく、カンマ区切りで渡す。この使い分けがよくわからなかったんだけれど、任意の数のパラメータを引数に渡す場合はapplyを使って、決まった数のパラメータを引数に渡す場合はcallを使うと良いってことだな。

TrackBack (0)

TrackBack URL: http://blog.1cco.com/mt/mt-tb.cgi/276

Post a Comment