PASCALには関数内関数というのがあって、好んで使っていたんだけど、JavaScriptならできるじゃんね。
Objective-Cには、ブロック構文というのがあって、同様のことができるらしい。他の言語でもクロージャが使えればいけるんじゃないかな。
即時関数で関数内を分割する
ある関数内を処理単位ごとに即時関数でブロック化する。
function(){
// 処理A。retAを生成するための処理
var retA = (function(){
...
})();
// 処理B
var retB = (function(retA){ // ブロック内で使う変数は、引数で取り込んでおくと分かりやすくて良い。
...
})(retA);
// 処理C
return (function(retA, retB){
...
})(retA, retB);
}
関数内でも関数化しておけば、関数化のメリット(ローカル変数と引数、戻り値を使って悪影響を減らす、処理の単位が明確になって可読性も上がる、など)は受けられ、将来的に分離する必要が出てきた時でも、既に関数になっているので簡単になる。
関数内関数のススメ
関数は小さくまとめた方がいい、と言う。うん、そうだね。だけど、関数化するかどうか悩むこともある。
例えば、その処理を、その関数内でしか使わない時。
例えば、その処理が他の関数から呼ばれてほしくない時。
ようするに独立性が低い時、かな。
関数化すると、その関数はグローバルになる。つまり、他の関数からも等しく見えてしまう。これは、オブジェクト化しても同じで、オブジェクトの内と外はあっても、オブジェクトの内部に階層はない。
内部でしか使用しないメソッドには、よくアンダースコアをつけたりして命名規則で意味付けをすることがあるけど、間違って使われてしまうことを避けられない。
さらにオブジェクト化すればいいけど、関数化も躊躇するときに、そこまでするのか?
そういう時でも、とりあえず関数でくくっとけ、と。特に開発中。
あとがき
JavaScriptにはブロックスコープがない、という記述を見かけて、気にしたことなかったな、と。
そういえば、C言語はブロックでスコープができることは、すっかり忘れてました。使った記憶は・・・ないなぁ。
PASCALでは関数内関数を好んで使ってたので、スコープを作るだけでもメリットはあったと思うのに・・・
そんなことを、つらつら考えているうちに、気づいたことをまとめてみました。