0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【JavaScript】関数と括弧について深掘り

0
Posted at

☆この記事でわかること☆

  • JavaScriptにおいて「関数」は特別な構文ではなく値の一種であること
  • 関数宣言と関数式の違い
  • edamameedamame() の決定的な違い(カッコの有無)
  • 初心者が絶対にハマる「なんで動かないんだ?」の鉄板パターン

はじめに

プログラミング学習をしていると「関数」って当たり前に使いますよね。
その中でJavaScriptにおける関数を

今回学んで「ほえー!」となったのは、
JavaScriptにおいて関数は"魔法の言語構造"ではなく、特別な種類の"値"である
ということです。この視点を持つと、カッコの有無でコードの挙動が
ガラッと変わる理由が分かってきます。

関数は「値」である

まずは普通の関数宣言から。

function edamame() {
  alert( "Hello" );
}

これとは別に、関数式と呼ばれる別の書き方があります。

let edamame = function() {
  alert( "Ho" );
};

この関数式を見ると、関数が他の任意の値と同じように
明示的に変数へ代入されているのがわかります。

つまり、どんな書き方で定義されても、関数は単に変数 edamame
に格納される「値」なのです。

カッコを付けないと実行されない

ここが第一のポイントです。

function edamame() {
  alert( "Hello" );
}

alert( edamame ); // 関数のコードそのものが表示される

最後の行、edamame の後にカッコがないため、
関数は実行されません。
かわりに、関数の中身(ソースコードの文字列表現)が表示されます。

JSでは関数は「値」なので、他のタイプの値と同じように扱えるわけですね。
edamame() のように呼び出せる点で特別ではありますが、あくまで値です。

関数はコピーできる

値なので、当然コピーもできます。

function edamame() {   // (1) 作成
  alert( "Hello" );
}

let func = edamame;    // (2) コピー(カッコ無し!)

func();  // Hello と表示   // (3) コピーの実行 → 動く!
edamame(); // Hello と表示   //     これも動く!

何が起きているか、順を追って見てみましょう。

  1. (1) 関数宣言で関数を生成し、変数名 edamame に格納
  2. (2) それを変数 func にコピー。ここで edamame の後に
    カッコがない点が超重要
  3. (3) これで edamame() でも func() でも呼び出せる

もし (2) でカッコを付けて let func = edamame();
と書いてしまうと、話が変わります。
それは edamame 関数自身ではなく、edamame呼び出した結果
func に書き込むことになります。

edamameedamame() の違い ~レシピの例え~

この違いを、料理のレシピで例えてみます。

  • edamame「関数そのもの」を指す。 レシピが書かれた紙そのもの
  • edamame()「関数を実行して、その結果をちょうだい」という意味。
    レシピ通りに料理して、出来上がった料理をもらうまで

image.png

カッコは「実行してね」という命令なんです。

コードで確認してみます。

function edamame() {   // (1) 関数を作成。変数 edamame に「関数そのもの」が格納
  alert("Ho");
  return 42;         //     実行されると 42 を返す
}

let a = edamame;       // (2) カッコ無し → 関数そのものを a にコピー
                     //     この時点では alert("Ho") は実行されない!(まだ料理してない)

let b = edamame();     // (3) カッコ有り → その場で edamame を実行
                     //     alert("Ho") のポップアップが出て、返り値 42 が b に入る

// ここから呼び出し ━━━━━━━━━━━━━

edamame();  // 元の関数を実行 → alert("Ho") が出て、42を返す
a();      // a は関数そのもの → 実行できる。alert("Ho") が出て、42を返す
b();      // エラー! b is not a function → b は数字の 42 なので実行できない

ここで a の中身は関数b の中身は 42 という数字。まったくの別モノです。

初心者ホイホイな罠

let func = edamame() とカッコを付けて書くと、
その場で edamame が実行されます
alert("Ho") がその瞬間に発動し、func には返り値(return した値)が入ります。

そして、return が無い関数だと func には undefined
が入る
という罠が待っています。

その状態で func() と呼び出そうものなら…

function edamame2() {
  alert("実行されました");
  // return が無い
}

let x = edamame2();  // alert が出て、x には undefined が入る
x();                 // エラー! x is not a function

「関数を代入したはずなのに、なんで動かないんだ?」となるわけです。
原因は、代入した瞬間に実行されてしまい、
中身が関数ではなく返り値(or undefined)に化けていたから。
初心者が踏み抜く鉄板パターンらしいので、要注意です。

まとめ

  • JavaScriptの関数は「魔法」ではなく、変数に格納できる"値"
  • edamame は「関数そのもの」、edamame() は「実行して結果をもらう」
  • カッコは「実行してね」の命令
  • カッコ付きで代入すると、その場で実行され、
    返り値(無ければ undefined)が入る → is not a function エラーの温床

やって良かったこと🌟

func = edamamefunc = edamame() の違いを、
レシピの紙 vs 出来上がった料理で例えられるようになったのがだいぶ収穫です。

これからも学んだことを記事化していきます。
ここまで読んでいただきありがとうございました!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?