(- prototype.js ajax) ビジュアル系じゃないprototype.js (3)
(1) d:id:smeghead:20070307:1173247173
(2) d:id:smeghead:20070307:1173247453
ソースを見るのはいろいろと勉強になります。
今日は、prototype.js(1.4.0)のEnumerableクラスの残りのメソッドを読んで、呼び出しました。
Enumerable.findAll
クロージャがtrueと評価する要素を配列で返却する。collect(map)は、クロージャが返した値を配列で取得するのに対し、findAllは戻り値がtrueになったクロージャの引数を配列で取得する。
下は、links要素の子要素中のAタグを取得している。
<script language="JavaScript"> Event.observe(window, 'load', testFunc, false); function testFunc() { var atags = $A($('links').childNodes).findAll( function(element) { if (element.tagName) { return element.tagName.match(new RegExp("a", "i")); } else { return false; } } ); alert(atags); } </script> <div id="links"> <a href="http://www.example.com/aaa">aaa</a><br> <hr> <a href="http://www.example.com/bbb">bbb</a><br> <hr> <a href="http://www.example.com/ccc">ccc</a><br> </div>
Enumerable.grep
要素を文字列に変換したものが引数のパターンと合致した場合は、引数のクロージャを適応する。クロージャを指定しない場合が、perlのgrepのような感じ。
下は、links要素の子要素なかのAタグ(文字列表現の結果がhttpを含む)の文字列(innerHTML)を配列で取得している。
<script language="JavaScript"> Event.observe(window, 'load', testFunc, false); function testFunc() { var atags = $A($('links').childNodes).grep(/http/, function(element, index) { return element.innerHTML; } ); alert(atags); } </script> <div id="links"> <a href="http://www.example.com/aaa">aaa</a><br> <hr> <a href="http://www.example.com/bbb">bbb</a><br> <hr> <a href="http://www.example.com/ccc">ccc</a><br> </div>
Enumerable.include
要素に引数のオブジェクトが含まれるかどうかを返却する。
下は、links要素の中にidがbbbLindのオブジェクトが存在するかどうかを返却する。
<script language="JavaScript"> Event.observe(window, 'load', testFunc, false); function testFunc() { alert($A($('links').childNodes).include($('bbbLink'))); } </script> <div id="links"> <a href="http://www.example.com/aaa">aaa</a><br> <hr> <a id='bbbLink' href="http://www.example.com/bbb">bbb</a><br> <hr> <a href="http://www.example.com/ccc">ccc</a><br> </div>
Enumerable.inject
各要素に対して、クロージャを実行する。injectの引数のmemoが、クロージャの第一引数となり戻り値にもなる(説明がむずかしい)ので、様々な使い方ができる。
prototype.js
inject: function(memo, iterator) { this.each(function(value, index) { memo = iterator(memo, value, index); }); return memo; },
あまりいい例が思いつかないですが、下はobjのb, d というプロパティを削除しています。
<script language="JavaScript"> var obj = {a: "aval", b: "bval", c: "cval", d: "dval"}; ["b", "d"].inject(obj, function(memo, element) { delete obj[element]; return obj; } ); for (var e in obj) { alert(e + ":" + obj[e]); } </script>
Enumerable.invoke
各要素に対して引数のメソッドを実行した結果を配列で取得する。引数を指定することもできる。
下は、各要素に対して、replaceメソッドを実行した結果を配列で取得している。
<script language="JavaScript"> var results = ["foo", "bar", "hoge"].invoke("replace", /o/g, "x"); alert(results); </script>
Enumerable.max
各要素の中の最大値を求める。
下は、配列の要素の中の最大値を求める
<script language="JavaScript"> alert([8, 4, 1, 5].max()); </script>
下は、配列のtallプロパティの最大値を求める。
<script language="JavaScript"> var john = {tall: 180}; var paul = {tall: 182}; var george = {tall: 181}; var ringo = {tall: 173}; var results = [john, paul, george, ringo].max(function(o){return o.tall;}); alert(results); </script>
Enumerable.min
各要素の中の最小値を求める。
下は、配列の要素の中の最小値を求める
<script language="JavaScript"> alert([8, 4, 1, 5].min()); </script>
下は、配列のtallプロパティの最小値を求める。
<script language="JavaScript"> var john = {tall: 180}; var paul = {tall: 182}; var george = {tall: 181}; var ringo = {tall: 173}; var results = [john, paul, george, ringo].min(function(o){return o.tall;}); alert(results); </script>
Enumerable.partition
各要素に対して適応したクロージャがtrueを返したものとfalseを返したものに分類し、それぞれを返却する。
下は、各要素の中のinstrumentsプロパティにguitarが含まれる人と含まれない人を同時に抽出している。
<script language="JavaScript"> var john = {name: "john", tall: 180, instruments: ["guitar", "piano"]}; var paul = {name: "paul", tall: 182, instruments: ["bass", "guitar", "piano"]}; var george = {name: "george", tall: 181, instruments: ["guitar"]}; var ringo = {name: "ringo", tall: 173, instruments: ["drums"]}; var results = [john, paul, george, ringo].partition(function(o){ return o.instruments.include("guitar"); } ); alert("guitarの人: " + results[0].map(function(o){return o.name;})); alert("guitarじゃない人: " + results[1].map(function(o){return o.name;})); </script>
Enumerable.pluck
pluckって意味が全く分からなかったのでとりあえず、検索した。
(鳥の)羽をむしる; (花・果実などを)摘む, 採る; ぐいと引っ張る, つかむ, つかもうとする; 救出する; 〔俗〕 奪い取る, 詐取する; (弦楽器を)かき鳴らす; 〔英古〕 落第させる.
要素の中の指定したプロパティの値を配列として取得する。
上のpartitionの最後の結果を表示する部分を、pluckを使って書き換えることができそうです。
<script language="JavaScript"> var john = {name: "john", tall: 180, instruments: ["guitar", "piano"]}; var paul = {name: "paul", tall: 182, instruments: ["bass", "guitar", "piano"]}; var george = {name: "george", tall: 181, instruments: ["guitar"]}; var ringo = {name: "ringo", tall: 173, instruments: ["drums"]}; var results = [john, paul, george, ringo].partition(function(o){ return o.instruments.include("guitar"); } ); alert("guitarの人: " + results[0].pluck("name")); alert("guitarじゃない人: " + results[1].pluck("name")); </script>
Enumerable.reject
クロージャがfalseと評価する要素を配列で返却する。
findAllの逆。
<script language="JavaScript"> var john = {name: "john", tall: 180, instruments: ["guitar", "piano"]}; var paul = {name: "paul", tall: 182, instruments: ["bass", "guitar", "piano"]}; var george = {name: "george", tall: 181, instruments: ["guitar"]}; var ringo = {name: "ringo", tall: 173, instruments: ["drums"]}; var results = [john, paul, george, ringo].reject(function(o){ return o.instruments.include("guitar"); } ); alert("guitarじゃない人: " + results[1].pluck("name")); </script>
Enumerable.sortBy
各要素の大小関係を数値に表すクロージャを引数に指定してソートを行う。
下は、各要素をinstrumentsプロパティの長さ順にソートし、最後にreverseすることで、たくさんの楽器を担当する人順に並べ替えている。
<script language="JavaScript"> var john = {name: "john", tall: 180, instruments: ["guitar", "piano"]}; var paul = {name: "paul", tall: 182, instruments: ["bass", "guitar", "piano"]}; var george = {name: "george", tall: 181, instruments: ["guitar"]}; var ringo = {name: "ringo", tall: 173, instruments: ["drums"]}; var result = [john, paul, george, ringo].sortBy(function(o){ return o.instruments.length; } ).reverse(); alert("たくさんの楽器を担当する人順: " + result.pluck("name")); </script>
Enumerable.toArray
各要素を配列に変更する。
??どうゆう意味かよくわからない。Enumerableを配列で実験してるからか?Hashまで進めばわかるのか??
保留
Enumerable.zip
複数の配列を引数にとり、それぞれの配列の同じindexの値の配列に変換する。
#他の言語のzip関数を見た時にもちゃんと理解してなかったので、説明が下手。
行列の行と列をひっくり返すようなイメージ?
最後の引数が’function’なら変換後の配列に適応する。
下は、array1とarray2の行と列をひっくり返す。
<script language="JavaScript"> var array1 = [1, 2, 3, 4]; var array2 = [100, 200, 300, 400]; var result = array1.zip(array2); result.map(function(a){alert(a);}); </script>
クロージャを渡す例を書こうとしましたが、どんな使い方をするか思いつきませんでした。呼び出し側のスコープの変数に副作用を与える使い方をするのかな?
Enumerable.inspect
調査した結果を返却します。
あれ?これ一見無限ループになりそうに見えるんだけどいいのかな?
さっきの意味が分からなかったtoArrayにも絡むのか?
prototype.js
inspect: function() { return '#<Enumerable:' + this.toArray().inspect() + '>'; }
下は、調査した結果をかえす。
<script language="JavaScript"> var array1 = [1, 2, 3, 4]; alert(array1.inspect()); </script>
#<Enumerable: [1, 2, 3, 4]>
と表示されることを期待していたんですが
[1, 2, 3, 4]
としか表示されない。
Array.inspect()が実行されているっぽいです。
Enumerable自体が実体化されないから呼び出されないメソッドという理解でいいんでしょうか?
今日のまとめ
わからない部分も多々ありますが、とにかくEnumerableが完了しました。
識者の方突っ込みお願いいたしますm(_ _)m
次は、Arrayの予定です。