関数の宣言されたコンテキストが環境になる

Web/JavaScript 講習会 part.6 (ホスト環境、オブジェクト、this、環境) — ディノオープンラボラトリで参考になったところをメモ。今回は、関数が宣言された位置で環境が決まるというお話だったと思う。


以下のような 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="template.js"></script>
                <title>Web/JS part.4 課題</title>
        </head>
        <body>
            <div id="kuma">
                   ∩_____∩<br />
               | ノ      ヽ<br />
              /  ●   ● | <span id="shout">クマ──!!</span><br />
              |    ( _●_)  ミ<br />
             彡、     |∪|  、`\<br />
            / __   ヽノ /´>  )<br />
            (___)    / (_/<br />
             |      /<br />
             |  /\  \<br />
             | /    )  )<br />
             ∪    (  \<br />
                   \_) <br />
            </div>
        </body>
</html>


例えば、以下のようなコードで書ける。

template.js
function prepareOverwrite() {
    document.getElementById("shout").innerHTML = "Javascript 楽しいクマー";
};
window.onload = prepareOverwrite;


だけど、このコードだと、セリフを変えるには prepareOverwrite() の中身をいじらなくてはならないので、関数としては汎用性が無い(要は prepareOverwrite() の引数でセリフを渡したいよねってこと)。そこで、JavaScript の「関数の宣言されたコンテキストが環境になる」性質を利用すると以下のようなコードが書ける。

template.js
var prepareOverwrite = function(stuff) {
  return function() {
    document.getElementById("shout").innerHTML = stuff;
  }
};
window.onload = prepareOverwrite("Javascript 楽しいクマー");