(- prototype.js ajax) ビジュアル系じゃないprototype.js (2)
(1) d:id:smeghead:20070307:1173247173
次は、本領発揮のArray系をやりたいと思います。
Array(配列)とHashに共通するメソッドがEnumerableに定義されているようです。
Enumerableで_each というメソッドを使ってるんですが、Enumerableには定義されていないです。その後インスタンス化されたオブジェクトには、常に存在するようになるので問題ないってことなんでしょうか?
Enumerable.each
これは、むちゃくちゃ強力です。mapとかinvokeとかinjectと合わせて関数プログラミングをサポートします。引数に受け取った関数(クロージャ?)を配列の各要素に適応します。ruby の each みたいな感じです。
try-catchの仕組みを使って、continue, breakの仕組みを実装してたんですが、javascriptって何でも投げれるのにびっくりしました。トリッキーになっちゃうけど、応用できるところがありそう。
var $break = new Object(); var $continue = new Object(); var Enumerable = { each: function(iterator) { var index = 0; try { this._each(function(value) { try { iterator(value, index++); } catch (e) { if (e != $continue) throw e; } }); } catch (e) { if (e != $break) throw e; } },
<script language="JavaScript"> //配列arrayの各要素を、alertで表示します。 var array = ["hello", "good bye"]; array.each(function(a) { alert(a); }); </script>
Enumerable.all
each同様に全ての要素を実行するが、クロージャがfalseを返したら繰り返しをやめる。
実装は、eachのところにあったtry-catchの仕組みでbreakを投げていました。クロージャの引数は、value(配列の要素値)、index(配列のindex)。
<script language="JavaScript"> var array = ["hello", "good bye", "the", "beatles"]; //index が2になったら繰り返しをやめる。 array.all(function(value, index) { alert(index + ":" + value); return index < 2; }); </script>
Enumerable.any
allに似てるけど、クロージャがtrueと評価される何かしらの値を返したら繰り返しを終了する。
<script language="JavaScript"> var array = [null, 0, 1, 2]; //1までalertで表示して繰り返しを終了する。 array.any(function(value, index) { alert(value); return value; }); </script>
Enumerable.collect
perlでいうところのmapです。配列の各要素へクロージャを適応してクロージャの戻り値を配列に格納して返却します。collectは、mapにエイリアスされています。
(この辺、もっと細かい話があるかも、クラスメソッドは、collectで、インスタンスメソッドは、map? でもよくわからない。メソッド定義の方法とかいろいろあるけどprototype.jsの中では、細かく制御してるんだろうか?)
<script language="JavaScript"> var array = ["hello", "good bye", "the", "beatles"]; var ret_val = array.collect(function(value, index) { return "[" + value + "]"; }); //[hello],[good bye],[the],[beatles]が表示される。 alert(ret_val); </script>
Enumerable.detect
anyに似てる。クロージャがtrueと評価される何かしらの値を返したら繰り返しを終了し、値を返却する。
<script language="JavaScript"> var array = [null, 0, 1, 2]; var ret_val = array.detect(function(value, index) { return value; }); //1を表示する。 alert(ret_val); </script>
区切りが悪いですが、次回につづきます。