30
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

NIJIBOXAdvent Calendar 2019

Day 17

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

Last updated at Posted at 2019-12-13

概要

ここに関数があります。

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。

参考まとめ

30
18
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
30
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?