Vueでメソッドの末尾に()
をつけた時とつけない時の挙動の違い
以前からVueを使っていて疑問だったことがありました。
それはVueのmethods
で定義したメソッド(関数)をテンプレートで使うとき、
末尾に()
をつけたメソッドと()
のないメソッドの両方を使用可能であるという事実です。
具体的にどういうことかコードで説明してみます。
下のコードでmethod
という名のメソッドがVueのmethods
プロパティで定義されているとします。
このときtemplate内から呼び出すときは、method()
とmethod
の両方が使えてしまいます。
(ちなみに<script></script>
タグ内では括弧無しの呼び出しmethod
は呼び出しになりません)
<template>
<!-- どちらの書き方でも正常に実行される -->
<div>
<div id="example1">
<!-- メソッド名(括弧無し)をv-onに渡した場合 -->
<button @click="method">括弧無し</button>
</div>
<div id="example2">
<!-- メソッド名(括弧有り)をv-onに渡した場合 -->
<button @click="method()">括弧有り</button>
</div>
</div>
</template>
はじめは、括弧なし呼び出しは括弧あり呼び出しの省略形ぐらいに考えていたのですが、調べてみたところ大きな違いがありました。
Vue詳しい方にとっては当たり前なのかもしれませんが、備忘録として残しておくことに。
調べてわかったこと
結論から書くと、次のような違いがあるということでした。
括弧あり呼び出し
- 引数無しの場合は引数は何も取らずに(当然ですが)、メソッドが呼び出されるだけ
- 引数がある場合も定義にしたがってメソッドが呼び出される
特に問題なく、普通のJSの関数(メソッド)と同じ挙動だと思います。
括弧なし呼び出し
- 引数として**
Event
オブジェクトが暗黙に渡され、**メソッドが実行される
一見、引数が何も無いので、単に引数無しのメソッドが呼び出されているように見えますが、実はそのDOMで発生したEventオブジェクトが引数にわたっています。
例を交えて
以下参考にしたページです。
- Parentheses while calling a method in Vue
- Method Event Handlers
- Difference when calling a method function with or without brackets
次の例では比較のためにブラウザのアラートを出す3種のボタンを用意してます。
VueのJS側では、対応するVueインスタンスのmethods
プロパティにsay()
というメソッドを用意しています。say()
メソッドは引数を1つ受け取るように定義されています。また、内部では受け取ったEventオブジェクトのタイプをJSのalert()
で表示する処理が書かれています。
See the Pen PoZLwYb by Masa U. (@masa_u1128) on CodePen.
まず、「括弧有り」ボタンをクリックすると、「TypeError: Cannot read property 'type' of undefined
」とアラート表示されます。引数を渡していないのでエラーが出るのは当然でしょう。
次に、「括弧無し」ボタンをクリックすると、「Eventオブジェクトのタイプはclickです」とアラート表示されます。
何...だと...?
繰り返しになりますが、引数は渡していません。これは引数に暗黙的にEvent
オブジェクトが渡されているためです。
最後に「括弧有り(引数に$event
を渡している)」ボタンを押してみましょう。この場合は引数に$event
という変数を渡してメソッド呼び出しをしています。結果は「括弧無し」ボタンと同じになります。ちなみに頭に$
のついた変数はVueであらかじめ用意された特殊な変数で、$event
はDOMイベントオブジェクトを格納する変数として使われます。
おそらく、括弧無し呼び出しのときは$event
が暗黙的に引数として渡されているということだと思います。
まとめ
以上のことから、括弧無し呼び出しでは暗黙的に引数にEvent
オブジェクトが渡されてることが分かりました。
普通に使っている分には括弧有りと無しのどちらを使っても問題ないような気がしますが、括弧無しの場合は1つ注意したいケースがあります。
それはデフォルト引数を使っている場合です。デフォルト引数があると、暗黙的に渡されるEventオブジェクトが引数となってしまうので、期待する結果と異なる結果が得られてしまいます。この場合は括弧有りの呼び出しを使うべきでしょう。
個人的には括弧をつけた方がぱっと見でメソッドであることが分かりやすく、算出プロパティと区別しやすいのでEventオブジェクトを使わない場合は括弧有り呼び出しを使った方がいいのかなと思っています。
(それにしても、公式ドキュメントを読んでもさらっと数行で済ましているので違いを理解するのに時間が少しかかった)