scala.js中的arguments.callee

时间:2014-12-02 08:32:42

标签: scala.js

我将此JavaScript函数移植到Scala.js:

once: function (el, type, callback) {
  var typeArray = type.split(' ');
  for (var i = typeArray.length - 1; i >= 0; i--) {
    el.addEventListener(typeArray[i], function(e) {
      e.target.removeEventListener(e.type, arguments.callee);
      return callback(e);
    });
  };
},

以下是我编写Scala代码的尝试:

def once(element: TopNode, tpe: String, callback: Function1[Event,Any]): Unit = {
  tpe.split(" ").foreach(item => element.addEventListener(item, (e : Event) => {
    e.target.removeEventListener(e.`type`, ?) // <-- what do I put here?
    callback(e)
  }))
}

如何在该占位符中引用我的lambda?

1 个答案:

答案 0 :(得分:4)

Scala.js没有等效的arguments.callee JavaScript。更一般地说,它没有等效的arguments。因此,lambda无法读取对自身的引用,除非通过其捕获的环境将其赋予它。这可以通过在val方法中将lambda存储在once中来实现。理想情况下,人们想写这个:

def once(element: TopNode, tpe: String,
    callback: Function1[Event,Any]): Unit = {
  val cb: js.Function1[Event, Any] = { (e: Event) =>
    e.target.removeEventListener(e.`type`, cb) // using cb here
    callback(e)
  }
  tpe.split(" ").foreach(item => element.addEventListener(item, cb))
}

但是,这不会编译,因为你不能在它的定义的右边使用val(这里是cb),即使它恰好在lambda中。尝试这样做会导致以下编译错误:

Main.scala:17: error: forward reference extends over definition of value cb
      e.target.removeEventListener(e.`type`, cb) // using cb here

但是有一个简单的解决方案:改为使用lazy val

def once(element: TopNode, tpe: String,
    callback: Function1[Event,Any]): Unit = {
  lazy val cb: js.Function1[Event, Any] = { (e: Event) =>
    e.target.removeEventListener(e.`type`, cb) // using cb here
    callback(e)
  }
  tpe.split(" ").foreach(item => element.addEventListener(item, cb))
}

请务必将cb声明为js.Function1,而不是Function1。否则cb本身将引用Scala函数,而不是自动转换产生的JS函数(具有不同的身份)。您必须确保cb引用JS函数。

小提琴:http://www.scala-js-fiddle.com/gist/2b848e2f01e7af522dc1