Qiitaからの移植


Scala.jsメモ3つ目

暗黙の型変換周りで躓いたのでメモ

環境

ソフトウェア バージョン
Scala 2.11.7
Scala.js 0.6.6

まとめ

  • JSに登録するイベントハンドラの型はjs.Function1[dom.Event, Any]にするべき

問題: removeEventListenerが上手く動かない

Scala.jsで,addEventListenerremoveEventListenerを使ったソースコードを書いていた. 元のJavaScriptの仕様通り,Scala.jsでも無名関数だとremoveEventListenerは使えないので,削除するためには,変数にキャプチャする必要がある.というわけで,

import org.scalajs.dom

val callback = (e: dom.Event) => {
  println("called")
}
button.addEventListener("click", callback)
button.removeEventListener("click", callback)

というコードを書いてみたが,removeEventListenerが働いてくれない.button.click()を呼び出すと,上のコードは,calledとコンソールに出力してしまう.

これは,addEventListenerremoveEventListenerの呼び出しの際,第二引数が,js.Function1[dom.Event, Any]にキャストされていて,それぞれの呼び出しでcallbackが指すオブジェクトが異なっていたからのようだ.

解決方法

変数にキャプチャする時点でキャストすれば良いので,

import org.scalajs.dom
import scala.scalajs.js

val callback: js.Function1[dom.Event, Any] = (e: dom.Event) => {
  println("called")
}
button.addEventListener("click", callback)
button.removeEventListener("click", callback)

とすれば想定通りcallbackを削除してくれる.試してはいないが(動いて満足したので),動作原理からいってjQueryの方も同様の問題(ないし仕様)が発生するのではないかと思う.