質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

1200閲覧

addEventListenerの挙動について

souta-haruran

総合スコア88

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2018/06/15 08:22

####addEventListenerの挙動について
以下のコードで、挙動が異なる原因が分からずつまづいています。
どなたか知見をお借りできますでしょうか。

html

1<ul id="ul-box"> 2 <li><img src="hoge1.png"></li> 3 <li><img src="hoge2.png"></li> 4 <li><img src="hoge3.png"></li> 5 <li><img src="hoge4.png"></li> 6 <li><img src="hoge5.png"></li> 7</ul>

下記JSのコードのaddEventListenerの第2引数の渡し方についてお伺いしたいです。
(1)

javascript

1var obj = { 2 targetElement: document.querySelector('#ul-box'), 3 setup: function() { 4 this.start(); 5 }, 6 move: function() { 7 // 上記htmlにある、横に複数並べられた画像が右から左に動くロジックが入ってます。 8 }, 9 start: function() { 10 var timer = setInterval(this.move.bind(this, function() { 11 this.move(); 12 }), 500); 13 this.targetElement.addEventListener('mouseover', this.stop(timer)); 14 this.targetElement.addEventListener('mouseout', this.start); 15 }, 16 stop: function(timer) { 17 return function() { 18 if (timer) { 19 clearInterval(timer) 20 } 21 } 22 } 23};

(2)

javascript

1var obj = { 2 // ここまでは上記(1)と同様なので割愛します 3 start: function() { 4 var timer = setInterval(this.move.bind(this, function() { 5 this.move(); 6 }), 500); 7 this.targetElement.addEventListener('mouseover', function() { 8 this.bind(timer); 9 }); 10 this.targetElement.addEventListener('mouseout', function() { 11 this.start(); // 再帰関数的な呼び出しになります 12 }); 13 }, 14 stop: function(timer) { 15 if (timer) { 16 clearInterval(timer) 17 } 18 } 19};

(1)と(2)で第2引数の渡し方が違うわけですが、以下のような挙動の違いがあります。

######(1)の場合(意図した挙動です)

  • ul要素上にマウスをのせると、右から左に動くアニメーションが停止します。
  • ul要素上からマウスをはずすと、アニメーションが再び動き出します。

######(2)の場合(意図してない挙動です)

  • ul要素上にマウスをのせても、右から左に動くアニメーションが停止しません。
  • ul要素上からマウスをはずすと、アニメーションのスピードが速くなります。

これを繰り返すことでアニメーションのスピードは速くなり続けます。

####私なりの見解
(1)はマウスをはずす度に予め用意されているstartメソッドを呼び出すだけ
(2)はマウスをはずす度に無名関数を登録しstartメソッドを呼び出すので、マウスをはずすという回数ほど『無名関数を登録』、『startメソッドが呼ばれる』ということになるので、startメソッド中で呼んでるmoveメソッドも同じくその回数ほど呼ばれ続けられることで、アニメーションのスピードが速くなり続けるのではないか?
という見解です。

ですが、これは私なりに調査した結果、「そうである可能性」というところまでしか分かりませんでした。
私の見解が全く違うということも当然考えられるわけですが、しかし(1)と(2)の挙動が違うという原因を知りたく質問いたしました。

####補足情報
今回質問させてもらっているコードについてはその昔社内の誰かが書いたコードであり、今回はそのコードは基本的に活かしたまま、部分的に改修する。という前提において嵌った問題です。
(1)の書き方では意図した挙動になっているので作業に問題はないものの、個人的にその理由が明確ではないままにしたくはなく、原因を知りたいと思い自分なりに調査しています。

どうかみなさんの知見をお借りできればと思います。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

(1)は正常に動く、という事で(2)のソースについて。

this.targetElement.addEventListener('mouseover', function() { this.bind(timer); });

↑何にtimerをbindしようとしてるのでしょう?
「this.stop」にbindするんじゃないの?

this.targetElement.addEventListener('mouseover', function() { this.stop.bind(timer); });

(2)はマウスをはずす度に無名関数を登録しstartメソッドを呼び出すので、マウスをはずすという回数ほど『無名関数を登録』、『startメソッドが呼ばれる』

↑これは推測どおり、mouseoutイベントが発生する度にsetIntervalされるので、moveメソッドが何度も実行されることになります。

投稿2018/06/15 09:49

tkturbo

総合スコア5572

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

souta-haruran

2018/06/15 09:58

tkturbo様 > this.bind(timer); すみません! これは完全に記述ミスでした。 正しくは、 this.stop(timer); と書きたかったのです。 つまりtkturbo様にご指摘いただいた this.stop.bind(timer); と同じことです。 失礼しました。 そして回答ありがとうございます。 推測どおりとの回答をいただき安心したと共に納得できました。 同時にもっと理解を深めるべきだと痛感しました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問