補足:sort() メソッドによる整列
お詫びです <(_ _)>
前回の記事を読み直しまして,余りに不親切であると反省いたしました.
元々,教員を退職した後,サイト全体が教材ではなく備忘録的な扱いになっておりまして,加えて Javascript と DOM(ウェブページの要素とでも考えてください)の操作は別物・・・といつの間にやら生意気な考えをするようになっておりました.
しかしながら,当初は学生の皆さんへの教材配布が目的でした.もう紙の時代ではないと.その内,ウェブページ内でグラフや図を動かして提示したいと考えまして,そのために Javascript を学びはじめたのが4~5年程前のことでした.ウェブページ内に図を描く Canvas が導入されたのは html5 の規格からでした.当時は,書籍がほとんどなく,エンジニアと思しき皆様のページを読みあさり書き方を覚えたものでございました.
今だ未熟者の分際で調子に乗っておりました.かなりの方々にお読みいただておりますことを鑑み,備忘録と言えど,もう少し丁寧な説明を心掛けて参ります.
関数リテラル
少々前の私であれば感じていた,いやいや今の自分でも感じている疑問について,多少の補足をしたいと思います.まずは,ここから参りましょう.リスト内の数値を数値として整列した場面です.
var cf = function(x, y) {
return x - y;
}
function sorting2() {
b.sort(cf);
document.getElementById('show2').innerHTML = b;
}
var cf = function(x, y) {・・・} と function sorting2() {・・・} の function の違いは何だ? 私は,夜も眠れぬほど疑問でした(アッ!私,不眠症を患っておりまして,眠れないのは毎日のことでした).結論から言えば,どちらも同じように関数を定義することができます.後者が通常の関数定義ですね.それに対して,前者を関数リテラルといいます.見てお分かりになるよう,関数に名前がありません.名前をつける必要がないのです.したがって,何度も使うことのない簡単な関数であれば,前者の書き方,つまり関数リテラルを用いた方が,手間を省けます.Javascript は,関数さえもオブジェクトとして扱います.関数リテラルを用いることで,その利点が一層際立ちます.b.sort(cf) の cf は,関数の戻り値ではなく関数そのものを表します.つまり,sort の引数として関数を渡しています.したがって,
b.sort(function(x, y) {return x - y;})
という書き方も許されるのです.ブレース括弧の外に丸括弧があると,数学の教員としてはもの凄く違和感があります.が,これは,数学的な扱いをするものではなく.関数の引数に関数を渡していると理解すれば納得できます(本当は,長年の経験から違和感アリアリですが・・・笑).
DOM とその操作
先ほども,DOM という言葉を使いました.Document Object Model の略です.ウェブページ内の要素のことだと思って間違いはないでしょう.ここでは,DOM の操作の概要(と言うより取っ掛かりでしょうか)をお話しします.
var cf = function(x, y) {
return x - y;
}
function sorting2() {
b.sort(cf);
document.getElementById('show2').innerHTML = b;
}
document.getElementById('show2').innerHTML = b;
とは何だ? 初心者・初級者の方には,ここも疑問ですよね.上には,Javascript しか載せてありませんが,実は,この部分には次の html が書かれています.
<p id="show2" class="c" style="font-family: monospace; white-space: nowrap;"> </p>
<p class="c"> <input type="button" value="reset" style="width:75px;" onclick="reset2();"> <input type="button" value="sort" style="width:75px;" onclick="sorting2();">
横に長く,見にくくなっており申し訳ありません.2つの<p></p>で囲まれたパラグラフが書かれています.
見ていただきたいのは,上のパラグラフに id="show2" という id が指定されていることです.併せて,中身は何も書かれていません.下のパラグラフは reset 及び sort というボタンが配置され,それぞれに reset2() と sorting2() の 関数が紐付けされています.class に関しては見なかったことにしてください.これは,私が,css ファイルで勝手に決めている書式です.まぁ,そうですねぇ,中央揃えする程度で.
それよりも,reset2() がどのような関数であるかを見ておく必要があります.
function reset2() {
for (i = 0; i < 10; i++) {
b[i] = Math.floor(90 * Math.random() + 10);
}
document.getElementById('show2').innerHTML = b;
まず,変数 b について,要素を 10 個持ったグローバルな配列変数です.さらに,Math 関数が2つ使われていますので,これについても説明します.
Math.floor()
フロア関数または床関数と呼ばれるものです.多くの皆さんには,高校の数学で扱ったガウス記号と言った方が馴染みがあるでしょう.フロートである引数を超えない最大の整数値を返します.例えば,Math.floor(3.14) の値は 3 となります.
Math.random()
0 以上 1 未満の乱数を返します.したがって,
Math.floor(90 * Math.random() + 10);
は,10 から 99 までの乱数を返します.C言語などと異なり seed は不要です.
document.getElementById('show2').innerHTML = b;
document は document クラスを表しまして,ウェブページの全体くらいに考えていてください.
getElementById('show2') は読んで字の如し,id を用いて要素を取得するとなり,show2 という id は空っぽのパラグラフに割り当てられていましたので,そのパラグラフとなります.
innerHTML は <p id="show2"></p> の内容を示し,このタグの中に b すなわち 10 個の 2 桁の乱数からなるリストが入り,表示されるということです.
リセットボタンをクリックまたはタップする度に,数値の列が変わるのは,以上の処理がなされているためです.下に,その状況をもう一度表示します.
上と比較して,ホンの少し見やすくなる工夫をしました.
イベントリスナ
簡単ではありますが,このページで行っている処理を説明して参りました.最後にもう一つ・・・
数値を並べた <p></p> は空だった筈なのに,reset ボタンをクリックする前から数値が表示されているのは何故だ? という疑問はないでしょうか?
最近の多くのアプリは,マウスで何かの操作をしたり,指でタップしたりするとそれに応じた動きをします.ウェブページに限らず,アプリには様々な要素が配置されており,これを仮にオブジェクトと呼ぶことにしましょう.オブジェクトには,イベントとプロパティが設けられています.
イベントからです.上で見た reset や sort のボタンでいうと onclick='関数' という形で関数が紐付けされていました.ボタンをクリックしたり,画面がドラッグしたりという動きなどをイベントといいます.onclick="sorting2();" とは,このボタンはクリックというイベントが発生すると,sorting2() という関数が動き出すという意味になります.このような仕組みをイベントドリブンといいます.世の中のコンピュータの OS が GUI になってからのアプリは,殆どがイベントドリブン型です.
続いて,プロパティです.<p></p> タグには innerHTML というプロパティが設けられており,これを変えると表示されるものが変化しました.<p></p> タグで言えば,文字色,背景色,フォントスタイル,フォントサイズ・・・挙げれば切りのない数のプロパティがあります.Javascript を用いると上の例のように,オブジェクトのプロパティを変えることができます.つまり,動的なウェブページを作ることができるのです.勿論,動的なウェブページを作るための言語は,PHP を筆頭に数多くあります.
さて,話しが膨らみました.元に戻しましょう.window そのものにもイベントとそれに対応した動きを指示することができます.
window.addEventListener('load', function() {
reset1();
reset2();
reset3();
reset4();
reset5();
});
window にイベントリスナを追加したと読めると思います.'load' は,window がロードされたとき,関数リテラルで書かれていますが,reset1() ~ reset4() を実行するという意味であることは,もうお分かりですね.したがって,このページが表示されるときには,すでに reset ボタンが押されたのと同じことが実行されているということです.