こんにちは
今回は僕がJavaScriptを書いているときにはまってしまった罠を共有しようと思います。
早速ですが、皆さんは下のコードがどのような振る舞いをするか分かりますか?
import "./App.css";
const App = () => {
const box = (name: string) => {
return (
<div className="box">
{name}
</div>
)
}
return (
<div className="App">
<div className="row">
<> {/*この中身の挙動を想像してみてください */}
{box("box1")}
{function () { return (box("box2")) }}
{() => { return (box("box3")) }}
</>
</div>
</div>
);
}
export default App;
なぜこのような挙動になるのか
一言で言うと関数の定義のみが行われて実行されていないからです。
開発者ツールでHTMLを見てみると、下の画像のようになります。
このようにbox1のみしか存在していません。
この記事をお読みのエンジニアの方々は「早く関数の宣言じゃなくて実行しろよ!!!」と思われているかもしれないので実行してみます。
即時実行関数の登場
<div className="row">
<>
{box("box1")}
{(function () { return (box("box2")) })()}
{(() => { return (box("box3")) })()}
</>
</div>
結果はこちらです
ちゃんと表示されました。
今回変更した点としては関数全体を囲む括弧と関数の後につけた括弧があります。
二つの括弧の説明としてMDNにいい感じの文章があったので引用します。
最初の部分は グループ化演算子 () に囲まれた静的スコープ付きの無名関数です。これは IIFE イディオム内で、汚いグローバルスコープと同様に変数へアクセスすることを防ぎます。
2つ目の部分は即時実行関数式の () で、これを通じて JavaScript エンジンは直接関数を解釈実行します。
つまり実際に実行するために動いているのは後ろの括弧です。
ではこの即時実行関数式はどのようなタイミングで使うべきなのでしょうか?
即時実行関数をいつ使うか問題を考えてみる
基本的にプログラムを書いているときは「宣言」→「実行」という流れが普通です。僕の肌感になりますが、宣言した瞬間に実行したい関数はあまりありません。そもそも関数は繰り返し行われる処理を簡単にするためであったり、プログラムの可読性を上げるために使います。
そのように考えていると、即時実行関数はおまけ機能くらいに思えてきます。ただ、私の中では一つ有用に使えるのではないかと思う場所があります。それはJSX Elementの中で式を利用しながら要素を作るときです。jsx Element内で関数を宣言してその後すぐに使うというよりも無名関数の即時実行関数で書いてしまった方が可読性が上がるのではないでしょうか?
結局普通の関数と違うところは宣言した瞬間に実行されるという一点になるので、この特徴を生かすために一回しか使われないような場面で使うというのが最もいいのではないでしょうか?
参考