高階関数バージョンのクマー

Web/JavaScript 講習会 part.9 (ぐりもんでXHR、Prototype) — ディノオープンラボラトリ」を見て参考になったところをメモ。


今回は、確か、prototypeスコープチェーンを理解してから、その応用例として高階関数があるよっていう流れで話が進んだと思う。


高階関数 - Wikipedia」によると、高階関数とはこんな感じの概念らしい。

高階関数(こうかいかんすう、英: higher-order function)とは、プログラミング言語において、関数を引数にしたり、あるいは関数を戻り値とするような関数の事である。引数や戻り値の関数もまた高階関数となり得る。これは主に関数型言語やその背景理論であるラムダ計算において多用される。数学でも同様の概念はあり、汎関数と呼ばれる。


関数を戻り値とするから JavaScript のクロージャも実は高階関数だったのかな?今回の例(higher_order.js)は引数に関数をとる関数を使っている。


今回の part9 で高階関数の説明に使われた例題は、前回とほぼ同じ処理(クマーにセリフを言わせる)を高階関数で実装し直したもの。以下に HTML と JavaScript のソースをメモっておく。


index.html のほうの内容は変わっていない。

index.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
        <head>
                <link rel="stylesheet" href="style.css" type="text/css" media="screen" charset="utf-8" />
                <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
                <script type="text/javascript" charset="utf-8" src="higher_order.js"></script>
                <title>Web/JS part.9</title>
        </head>
        <body>
            <div id="kuma">
                   <span id="year">∩_____∩</span><br />
                   <span id="head">| ノ      ヽ</span><br />
                  <span id="eyes">/  ●   ● | </span><span id="shout">クマ──!!</span><br />
                  <span id="nose">|    ( _●_)  </span><span id="hige"></span><br />
                 <span id="mouth">彡、     |∪|  、`\</span><br />
                <span id="neck">/ __   ヽノ /´>  )</span><br />
                <span id="body">(___)    / (_/</span><br />
            </div>
        </body>
</html>


高階関数を使っているだけで、前回とほぼ処理内容は変わらない(getShout関数を省略しただけ)。慣れればこちらのほうがすっきりしていて読みやすいかもしれない。

higher_order.js
// higher-order でクマーにセリフを言わせる
window.onload = function() {
  Object.prototype.forEach = function(fn) {
    // ここの for in 文に関してはサイ本 p91 が参考になる
    for(var p in this) {
      fn(this[p]);
    }
  };

  var CATALOG = {
    ear: 'みみ', ear: 'みみ', head: 'あたま', eyes: 'め', nose: 'はな',
    mouth: 'くち', neck: 'くび', body: 'からだ'
  };
  document.getElementsByTagName('span').forEach(function(elm) {
                                                  if (CATALOG[elm.id]) {
                                                    elm.onclick = function() {
                                                      document.getElementById('shout').innerHTML = CATALOG[elm.id];
                                                    };
                                                  }
                                                });
}