公開日:2007.12.17
関数オブジェクト - 基本
今回は参照型のオブジェクトの中でも関数型と呼ばれる オブジェクトについてお話します。
関数型オブジェクト
一般的にJavaScriptで関数を宣言するには function という指示子に続けて ”関数名”、”引数”、”処理内容”と記述する事で 関数を宣言できます。 こんな感じですね。
function my_func(str) {
alert(str);
}
実はこの関数も通常のオブジェクトです。 この関数宣言を別の書き方で書いてみましょう。
my_func = new Function("str", "alert(str)");
こう書いた方がオブジェクトらしいのではないでしょうか。
一般的な関数宣言は言い換えると 「my_methodという名で関数型のオブジェクトを作成せよ」 という命令を行っているのと同じで、 「関数リテラル」という表現方法なんです。
前回「オブジェクトリテラル」という表現が出てきましたが、 あれはオブジェクトのリテラル表記で、今回は関数です。
リテラルとはソース上に直接、値を書く方法で、 文字列リテラルだと"hoge"のように"で挟んで書きますね。 同様に["a", "b"]などは配列のリテラルです。
関数型オブジェクトの実行
話が逸れましたが、関数宣言とは関数オブジェクトを作成して、 変数にセットすることです。 変数にセットするという事は、関数も他の変数にセットできる値と 同じように扱う(コピーしたりする)事ができるということです。 そしてその変数に()を付けて呼び出す事でその関数を実行できます。
my_func = new Function("str", "alert(str)");
my_func("ほげほげ");
//⇒『ほげほげ』と表示
other_func = my_func;
other_func("ふがふが");
//⇒『ふがふが』と表示
また、変数にセットするというは オブジェクトのプロパティにセットするという意味でもあります。 オブジェクトを省略した場合、 セットするオブジェクトはwindowとなります。
windowオブジェクトのプロパティなので前回説明した別の方法で 関数を呼び出す事もできます。
window["my_func"]("hoge");
//⇒『hoge』と表示
普段、使い慣れているalertやprompt,open等も 全てwindowオブジェクトのプロパティにセットされた関数です。 もちろんコピーも上書きもできます。
my_func2 = window.prompt;
my_func2("foo");
//⇒プロンプトを表示する
プロパティはオブジェクト毎に存在するので、 文字列オブジェクトだとまた別のプロパティを持っています。
"abcde".indexOf("b");
//⇒1
"abcde"["indexOf"]("d");
//⇒3
関数リテラルと無名関数
関数オブジェクトを作成して変数にセットという処理は、 関数リテラルとして書くことができます。
window.my_func = function(str){ alert(str) };
実は関数リテラル表記には名前を付ける必要がありません。 変数にセットする事で呼び出せますからね。 またその関数を1回しか呼び出さないならこんな書き方もできちゃいます。
(function(str){ alert(str) })("hogehoge");
一回しか使わないんなら関数である必要なさそうなので、 意味のない書き方に見えるかもしれませんが、 活躍する場面が多いです。これについてはまたの機会に説明します。
関数には名前を付ける必要がないと説明しましたが、 この関数を無名関数と呼びます。 上の例だとの右辺のfunction以降ですね。 無名関数を別名クロージャと言います。 特別な名前がついていますがいつもの書き方を変えただけですよね。
実はこのクロージャこそが現在のJavaScriptの肝といっても 過言ではない機能の一つなんです。 次回はこのあたりをもうすこし掘り下げて説明したいと思います。
まとめ
- 関数もオブジェクトである
- 一般的な関数宣言は関数オブジェクトのリテラル表現
- 関数オブジェクトがセットされた変数に括弧をつける事でその関数を実行できる
