Help us understand the problem. What is going on with this article?

JavaScriptのイベント指定 〜括弧()をつける?つけない?〜

概要

ここに関数があります。

function func() {
  console.log('hoge');
};

通常は

func();

関数名()のような形で関数を実行するのに、

window.onloadなどイベントハンドラを利用して関数を実行する場合は、

window.onload = func;

関数名のみで書くのはなぜなんでしょう。

イベント処理の指定方法

JavaScriptのイベント指定には3種類の方法があります。

(1) addEventListener()によるイベントリスナの指定
(2) オブジェクトに指定するイベントハンドラ
(3) HTMLタグ属性に指定するイベントハンドラ

(1) addEventListener()によるイベントリスナの指定

window.addEventListener('load', func);

第1引数にイベントタイプ、第2引数に実行される関数(コールバック関数)を指定しています。
上記例ではloadイベントが検知されると同時にコールバック関数が実行されるので、func()はつけません。

もし第2引数をfunc()のように括弧をつけて書いてしまうと、JavaScriptが読み込まれた時点でfunc関数が実行されてしまいます。
(loadよりも早いタイミングで関数が実行される。)

// これはNG
window.addEventListener('load', func());

// これはOK
window.addEventListener('load', function() {
  func();
});

(2) オブジェクトに指定するイベントハンドラ

window.onload = func;

これはwindowオブジェクトのonloadプロパティにfuncという関数を代入しますよ、という意味です。
window.onloadメソッドはすべてのDOMツリー構造及び関連リソースが読み込まれたあとに自動で発生するので、func関数に関数実行を意味する()をつけないのが正しいです。

もしwindow.onload = func()のように書いてしまうと、JavaScriptが読み込まれた時点でfunc関数が実行され、その戻り値がwindow.onloadメソッドに代入されるだけとなってしまいます。

// これはNG
window.onload = func();

(3) HTMLタグ属性に指定するイベントハンドラ

HTML
<input type="button" id="button" onclick="func()">

html要素の属性を用いてonclick="func()"とイベントハンドラを指定することができます。
ただ(1)、(2)の説明だとfunc()と関数に括弧がついているので、htmlが読み込まれた時点で関数が実行されてしまうのでは?と疑問に思っていました。

調べたところブラウザが属性を読みとると、その内容から本体を含むハンドラ関数が作成されるようです。
つまりこの記述は以下と同じ意味になります。

JS
button.onclick = function() {
  func(); // ここにハンドラ属性に指定した値がはいる
};

ハンドラ関数の中身に属性値がそのまま入るので、括弧がなければ関数が実行されません。
よってhtml属性に指定する場合は関数名()とする必要があります。

HTML
<!-- こう書いてしまうと、 -->
<input type="button" id="button" onclick="func">
JS
button.onclick = function() {
  func; // func関数が実行されない
};

どのイベント指定を使えば良い?

(3)のようにHTMLとJavaScriptを混在させる書き方は好ましくありません。

(1)addEventListener()(2)オブジェクトに指定だと、どちらかといえば(1)addEventListener()推奨のようです。

理由
・必要に応じてremoveEventListener()でイベントハンドラコードを削除できる
・要素に同種のリスナーを複数追加できる

(1)addEventListener()によるイベントリスナの指定
// 同種のリスナーを複数追加できるので、
// console.log('hoge')、console.log('fuga')の両方実行される。

window.addEventListener('load', function() {
  console.log('hoge');
});

window.addEventListener('load', function() {
  console.log('fuga');
});
(2)オブジェクトに指定するイベントハンドラ
// 上書きされて最後に書いたイベントのみ実行されるので、
// console.log('fuga')のみ実行される。

window.onload = function(){
  console.log("hoge");
};

window.onload = function(){
  console.log("fuga");
};

最後に

window.onload = func;に括弧がいらない理由を知らなくてもJavaScriptは書ける。
けど、知ってたらもっと楽しいJavaScript。

参考まとめ

nb_tomo
フロントエンドエンジニア3年生。日々勉強していきたい。。
nijibox
ニジボックスの開発は、社内のUI/UXデザインチームと連携をとりながらワンストップで行う開発支援サービスです。Reactを始めPHP(Laravel)・Ruby on Rails、Swift・Kotlinを使った開発実績も多く、バックエンドからアプリまで幅広く対応しています。Twitterで情報発信しています: https://twitter.com/nijibox_jp
https://nijibox.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした