【JavaScript】関数を変数に代入する方法は?メリットはある?
JavaScriptでは非常に使用頻度が高い関数ですが、実は数字や文字列などと同じく、データとして変数に代入することができます。
今回は、関数を代入することにどのようなメリットがあるのか、初心者向けにわかりやすく解説していきます。
【前提】関数を代入する方法
本題に入る前に、まず関数を代入・定義する方法について簡単に説明します。
例えば、JavaScriptで関数を定義する場合は、以下のようなコードを書くのがオーソドックスな方法ですよね。
function sample(){
// 実行したい処理
}
この場合、”sample”という部分を関数名と呼び、この関数名を書くことで関数名の呼び出し処理を記述します。ただ、もちろんこれは変数に代入されていない形式の関数です。
変数に関数を代入したい場合は、以下のように無名関数という関数の記述を用います。
/* 関数名を付けずに関数を書く */
let sample = function(){
// 実行したい処理;
}
// 実行
sample();
/* アロー関数を使う場合 */
let sample = ()=>{
//実行したい処理
}
一般的に無名関数はコールバック関数を直接書く場合などに用いますが、変数に代入すれば、その変数名を呼び出すことで代入した関数を実行することができます。
ちなみに、一応変数名と関数名を両方指定するような書き方もあり、そっちはそっちで再帰処理を書きやすくなるなどのメリットがあったりします。
変数に代入する3つのメリット
変数に関数を代入するメリットとして、主に以下の3つのものがあります。
- 関数を配列・オブジェクトで管理できる
- 関数内でグローバルな関数を定義できる
- 関数を簡単に削除できる
もちろんこれらの他にもメリットはあると思いますが、この記事では以上3つのメリットにフォーカスして解説していきます。
1.関数を配列・オブジェクトで管理できる
関数を変数に代入できるということは、すなわち配列やオブジェクトのデータとしても扱えるということです。
単刀直入に言うと、以下のように一定時間で加算値を変更するようなプログラムを、配列の添字を変更することで実現できるようになります。
// 初期値
var num = 0;
// 異なるアルゴリズムを持った関数を格納した配列
const funcs = [
function(){
num++;
},
function(){
num-=0.5;
},
function(){
num+=100;
}
];
// 要素ごとに実行する関数を遷移させる処理
var index = 0;
var count = 0;
// 1秒ごとに計算用のアルゴリズム実行
setInterval(()=>{
funcs[index]();
count++;
if(count >= 3){
index++;
count = 0;
if(index >= funcs.length){
index = 0;
}
}
console.log(num);
}, 1000);
変数の値で関数を管理可能になったことで、一風変わった計算アルゴリズムが組めました。
このプログラムだけでも、ランダムに実行する関数を選べるようにする等、色々と工夫のし甲斐がありますね。
一般に定義しただけの関数を使ってこういった処理を実現するのは面倒なので、WEBゲームのように複雑なプログラムを実装する際には重宝するかもしれません。
2.関数内でグローバルな関数を定義できる
JavaScriptをはじめ、多くのプログラミング言語には「関数の入れ子」という考え方があります。
関数の入れ子というのは、以下のようにある関数の中で別の関数を使役することを言います。
// 関数parent
function parent(){
// 関数son(関数内定義)
function son(){
let text = "関数sonが実行されています。";
return text;
}
// 関数sonの返り値(変数text)を返す
return son();
}
// 関数を実行し、出力
let msg = parent();
console.log(msg);
上記のコードを実行すると、関数parent内で定義し、実行した関数sonが機能していることがわかりますね。
ただし、上記のコードの場合、関数sonは関数parentのスコープ内で扱える関数であり、プログラム全体から関数sonだけを呼び出すことはできません。
そんな関数内で定義した関数を他所でも呼び出したいときに利用するのが、グローバル変数です。
先ほどにコードにグローバル変数を活用し、関数を外から呼び出せるよう改変したものが以下のコードになります。
// 代入用グローバル変数
var globalSon;
function parent(){
// 定義した変数に関数を代入
globalSon = function(){
let text = "関数sonが実行されています。";
return text;
}
}
// 変数globalSonに関数を代入する
parent();
// 関数を実行し、出力
let msg = globalSon();
console.log(msg);
上記のコードを実行すると、globalSon( )というコードを記述すれば、いつでもどこからでも関数が呼び出せるようになります。
ただ、こんな回りくどいことをするなら、以下のように初めから同様の関数を定義している方が早いです。
function globalSon(){
let text = "関数sonが実行されています。";
return text;
}
console.log(globalSon());
非常にすっきりとしたコードに様変わりしましたね…
以上のことから、これはあまり実用的ではないメリットですが、頭の片隅に置いておくと、どこかで使う機会はあるかもしれません。
(不正に呼び出されたくない関数は特定の関数実行時に定義することで、不正対策にはなる)
3.関数を簡単に削除できる
変数に関数を代入しておけば、いつでも好きなときに関数を削除できるようになります。削除するというよりは、値の再代入を行うことで、事実上関数の存在を上書きするイメージです。
例えば以下のようなコードを実行すると、途中で関数の値が上書きされ、それ以降関数の処理が実行されなくなることがわかります。
// 関数を代入
let func = function(i){
console.log(`${i}回目の処理です。`);
}
/* 関数の実行処理 */
let count = 0;
setInterval(()=>{
if(count == 3){
// 3回、処理を繰り返したら関数を削除
func = "";
}
count++;
func(count);
}, 1000);
処理の途中で役目を終えるような関数がある場合など、途中で関数の存在を消したい場合には役立つかもしれません。
まとめ
JavaScriptにおいて関数は非常に便利なものですが、ただ定義するだけだと管理がしにくかったり、取り扱いに困ったりと、少しデメリットも出てきます。
より扱いやすいプログラムを構築するためにも、使いまわしたい便利な関数は変数や配列・オブジェクトに代入しておくなどして、データとして再利用できる状態にしておくのがおすすめです。