prototype.js version 1.4.0系でのEnumerableの使い方

Ruby on Railsなどのフレームワークに標準付属されていて、オブジェクト指向なJavaScriptを書く人たちの間で注目されているprototype.jsですが、Version 1.3.1時点での機能についての解説書は見つけたものの(prototype.js v1.3.1 の使い方)、1.4系で盛り込まれるであろうEnumerableについては見つけることができませんでした。なので、Version 1.4.0_rc4時点でのEnumerableについて解説してみます。

Enumerableとは、配列やハッシュなどのデータ構造に対して繰り返し処理をさせるための機能を集めたものです。たとえば配列に入っている値それぞれについて処理を行いたかった場合、従来ならば以下のように書いていたでしょう。

var data = [1,2,3,4];
for(var i=0; i<data.length; i++){
//do something ...
alert(data[i]);
}

Enumerableなオブジェクトに対しては以下のように書くことができます(prototype.jsをインクルードするとArrayクラスはEnumerableになります)。

var data = [1,2,3,4];
data.each(
function(value,index){
//do something ...
alert(value);
}
);

これは俗にIteratorパターンと呼ばれるものです。こうすることで何が良くなるのでしょうか。

たとえばdata{a:1, b:2}のようにハッシュに変わった場合、従来通りのやり方だとforループを以下のように書き換える必要がありました。

var data = {a:1, b:2};
for(var key in data){
//do something ...
alert(data[key])
}

しかし、Enumerableなハッシュに対しては、配列の時と同じようにeach()関数を呼べばすみます($H()関数は引数のオブジェクトをEnumerableなハッシュにする関数です)。

var data = $H({a:1, b:2});
data.each(
function(pair, index){
//do something ...
alert(pair.value); //or alert(pair[1]);
}
);

このようにデータ構造が変わったとしても、Enumerableなオブジェクトのそれぞれの値にアクセスしたい場合はeach()を呼べば大丈夫と言うことで、繰り返し処理部分のコードの共通化を行うことができます。

prototype.jsではArrayとHashとRangeオブジェクトについてはprototype.jsをインクルードした時点でEnumerableになります。それ以外の自分の定義したオブジェクトをEnumerableにしたい場合は、そのオブジェクトにIterator関数を引数に取る_each()関数を定義してあげる必要があります(なぜならばEnumerableの各種機能は_each()関数を内部的に呼び出すことで機能しているため)。

たとえばArrayをEnumerableにするためのコードは以下のようになります(prototype.jsから拝借)。

Object.extend(Array.prototype, Enumerable); //Enumerableに定義されている関数をArray.prototypeにコピー

Object.extend(Array.prototype, {
_each: function(iterator) { //Enumerableで必須の_each()関数の定義
for (var i = 0; i < this.length; i++)
iterator(this[i]);//Arrayのそれぞれの値をIterator関数に渡している
}
});

さてここからはEnumerableで定義されている各種関数について解説していきます。(Rubyリファレンスマニュアル - Enumerableを参考にしました)

関数 each(iterator)
役割 Enumerableなオブジェクトのそれぞれの要素にアクセスする
使用例
var data = [1,2,3,4];
data.each(
function(value,index){
//do something ...
alert(value);
}
);
関数 all()
役割 すべての要素が真(undefinedまたはnullまたは0でない)である場合、trueを返す。偽(undefinedまたはnullまたは0)である要素があれば、直ちにfalseを返す。
使用例
var data = [1,2,3,4];
data.all();
//この場合、undefinedまたはnullまたは0な要素がないのでall()関数はtrueを返す。
関数 all(iterator)
役割 すべての要素が真である場合、trueを返す。偽である要素があれば、直ちにfalseを返す。iterator関数はそれぞれの要素が真か偽かを検査するための関数。
使用例
var data = [1,2,3,4];
data.all(
function(value,index){
return value>2 ? true : false;
}
);
//この場合、配列の中に2以下の値が入っているのでall()関数はfalseを返す。
関数 any()
役割 すべての要素が偽(undefinedまたはnullまたは0)である場合、falseを返す。真(undefinedまたはnullまたは0でない)である要素があれば、直ちにtrueを返す。
使用例
var data = [1,2,3,4];
data.any();
//この場合、配列の中に真(undefinedまたはnullまたは0でない)の要素があるのでany()関数はtrueを返す。
関数 any(iterator)
役割 すべての要素が偽である場合、falseを返す。真である要素があれば、直ちにtrueを返す。iteratorはそれぞれの要素が真か偽かを検査する関数。
使用例
var data = [1,2,3,4];
data.any(
function(value,index){
return value>5 ? true : false;
}
);
//この場合、配列の中に5以下の値が入っていないのでany()関数はfalseを返す。
関数 collect(iterator)
map(iterator)
役割 それぞれの要素についてiteratorを実行した結果を配列として返す関数。
使用例
var data = [1,2,3,4];
data.collect(
function(value,index){
return value+1;
}
);
//この場合のcollect()の戻り値は[2,3,4,5]
関数 detect(iterator)
find(iterator)
役割 それぞれの要素についてiteratorを実行し、iteratorが真を返した時の要素を返す関数。すべての要素に対してiteratorが真を返さなかった場合の戻り値はundefined。
使用例
var data = [1,2,3,4];
data.detect(
function(value,index){
return value>2 ? true : false;
}
);
//この場合、2を超える値は3なので3を返す。
関数 findAll(iterator)
select(iterator)
役割 それぞれの要素についてiteratorを実行し、iteratorが真を返した要素を配列で返す関数。すべての要素に対してiteratorが真を返さなかった場合の戻り値は[]。
使用例
var data = [5,3,2,4];
data.findAll(
function(value,index){
return value>3 ? true : false;
}
);
//この場合、3より大きい要素は5と4なので[5,4]を返す。
関数 grep(pattern)
役割 それぞれの要素についてpattern(正規表現)を適用し、patternがマッチした要素を配列で返す。すべての要素に対してpatternがマッチしなかった場合の戻り値は[]。
使用例
var data = ['macromedia Dreamweaver','macromedia Flash', 'Adobe Photoshop', 'Adobe Illustrator'];
data.grep(
/macromedia/
);
//この場合の戻り値は['macromedia Dreamweaver','macromedia Flash']
関数 grep(pattern, iterator)
役割 それぞれの要素についてpattern(正規表現)を適用し、patternがマッチした場合、その要素についてiteratorを実行し、その実行結果を配列で返す。すべての要素に対してpatternがマッチしなかった場合の戻り値は[]。
使用例
var data = ['macromedia Dreamweaver','macromedia Flash', 'Adobe Photoshop', 'Adobe Illustrator'];
data.grep(
/macromedia/,
function(value, index){
return value.toUpperCase();
}
);
//この場合の戻り値は['MACROMEDIA DREAMWEAVER', 'MACROMEDIA FLASH']
関数 include(object)
member(object)
役割 それぞれの要素の中にobjectと等しいものが入っていればture、入っていなければfalseを返す。
使用例
var data = [1,2,3,4];
data.include(1);
//この場合、dataに1が含まれているので戻り値はtrue。
関数 inject(memo, iterator)
役割 初期値memoと要素の値を元にiteratorを実行する。
使用例
var data = ['+', 'Adobe'];
data.inject(
'macromedia',//初期値
function(memo, value, index){
return memo += value;
}
);
//この場合の戻り値は"macromedia+Adobe"。
関数 invoke(method, argument1, argument2, ...)
役割 それぞれの要素の関数methodを呼び出し、その実行結果を配列で返します。
使用例
var data = [
{
methodA: function(msg){return 'methodA ' + msg;},
methodB: function(msg){return 'methodB ' + msg;}
},
{
methodA: function(msg){return 'another methodA ' + msg;},
methodB: function(msg){return 'another methodB ' + msg;}
}
];
data.invoke(
'methodA',//こちらは呼び出すメソッド名
'invoked!'//こちらはメソッドに渡す引数(複数可)
);
//この場合の戻り値は['methodA invoded!', 'another methodA invoked!']。
関数 max()
役割 要素の中で最大の値を返す関数。要素の比較は>=演算子を使って行われます。
使用例
var data = [4,2,3,1,-5];
data.max();
//この場合の戻り値は4。
関数 max(iterator)
役割 それぞれの要素にiterator関数を実行し、その実行結果の中で最大の値を返す関数。要素の比較は>=演算子を使って行われます。
使用例
var data = [4,2,3,1,-5];
data.max(
function(value, index){
return -1*value;
}
);
//この場合の戻り値は5。
関数 min()
役割 要素の中で最小の値を返す関数。要素の比較は<=演算子を使って行われます。
使用例
var data = [4,2,3,1,-5];
data.min();
//この場合の戻り値は-5。
関数 min(iterator)
役割 それぞれの要素にiterator関数を実行し、その実行結果の中で最小の値を返す関数。要素の比較は<=演算子を使って行われます。
使用例
var data = [4,2,3,1,-5];
data.min(
function(value, index){
return -1*value;
}
);
//この場合の戻り値は-4。
関数 partition()
役割 それぞれの要素について真か偽かを判定し、真のものと偽のものをそれぞれ配列に入れて返します。
使用例
var data = [4,2,3,0,-5];
data.partition();
//この場合の戻り値は[[4, 2, 3, -5], [0]]。
関数 partition(iterator)
役割 それぞれの要素についてiteratorを実行し、その結果が真か偽かを判定し、真のものと偽のものをそれぞれ配列に入れて返します。
使用例
var data = [4,2,3,0,-5];
data.partition(
function(value, index){
return value > 0 ? true : false;
}
);
//この場合の戻り値は[[4, 2, 3], [0, -5]]。
関数 pluck(property)
役割 それぞれの要素について、その要素のpropertyの値を取得し、配列に入れて返します。
使用例
var data = [
{
propA: "propA",
propB: "propB"
},
{
propA: "another propA",
propB: "another propB"
}
];
data.pluck('propA');
//この場合の戻り値は["propA", "another propA"]。
関数 reject(iterator)
役割 それぞれの要素についてiteratorを実行し、その実行結果が偽であるものについて、その要素を配列に入れて返します。
使用例
var data = [1,2,3,4,5];
data.reject(
function(value, index){
return value > 3 ? true : false;
}
);
//この場合の戻り値は[1, 2, 3]。
関数 sortBy(iterator)
役割 それぞれの要素についてiteratorを実行し、その実行結果順にソートします。
使用例
var data = [-5,4,-3,2,-1];
data.sortBy(
function(value, index){
return value*value;
}
);
//この場合の戻り値は[-1,2,-3,4,-5]。
関数 toArray()
entries()
役割 すべての要素を含む配列を返します。
使用例
var data = "macromedia";
data.toArray();
//この場合の戻り値は["m", "a", "c", "r", "o", "m", "e", "d", "i", "a"]。
関数 zip()
役割 それぞれの要素と、引数に渡した要素からなる配列を生成します。
使用例
var data = [1,2,3];
data.zip(
[4,5,6],
[7,8,9]
);
//この場合の戻り値は[[1,4,7],[2,5,8],[3,6,9]]。
関数 zip(..., iterator)
役割 それぞれの要素と、引数に渡した要素からなる配列を生成し、生成された配列の各行に対してiteratorを実行します。
使用例
var data = [1,2,3];
data.zip(
[4,5,6],
[7,8,9],
function(ary){
alert(ary.inspect());
}
);
//この場合はalert([1,4,7]); alert([2,5,8]); alert([3,6,9]);と言うコードと等価です。

Leave a Reply

Your email address will not be published. Required fields are marked *