将 Scala.js class 实例传递给将调用函数调用方法的 JavaScript

Pass Scala.js class instance to JavaScript that will invoke the function call method

我有一个简单的 Scala.js class(Scala-2.12.10 和 Scala-js 0.6.31):

class Foo extends js.Object {
def apply() = { println("apply") }
def bar() = { println("bar") }
}

val myfoo = new Foo()

Foo 的实例将被传递给 JavaScript 库,该库将依次尝试调用以下两个方法:

myfoo()
myfoo.bar()

当然,这是行不通的,因为我无法在 Foo 上定义 apply 方法,因为它派生自 js.Object,并且不会转换为对对象调用 ()

如何构建适合这种情况的 class?

更新:

这是一些基于@sjrd 的回答的示例代码,在封装 js.Dynamic 复杂性的同时提供强类型。

trait FooTrait extends js.Object {
  def own()
  def bar()
}

class Foo extends FooTrait {
  def own() = { println("apply") }
  def bar() = { println("bar") }
}

def makeFoo(foo: FooTrait]) = {
  val jsFoo = ({ () => 
    foo.own()
  }: js.Function0[Unit]).asInstanceOf[js.Dynamic]

  jsFoo.bar = ({ () =>
    foo.bar()
  }: js.Function0[Unit])

  jsFoo
}

val myFoo = makeFoo(new Foo())

现在 myFoo 已准备好传递到 JavaScript 图书馆。

在 JavaScript 中,像 myfoo() 这样的调用有效的唯一方法是 myfoo 创建的 作为函数值.要使 myfoo.bar() 额外工作,必须在函数值创建后对其进行修补。没有办法(代理除外,它完全是另一种野兽)首先创建 myfoo 作为对象,无论是否来自 class,并使其响应 myfoo().

因此,这也是你在Scala.js中要做的:

val myfoo = ({ () =>
  println("apply")
}: js.Function0[Unit]).asInstanceOf[js.Dynamic]
myfoo.bar = ({ () =>
  println("bar")
}: js.Function0[Unit])

之后,您可以将myfoo传递给JavaScript代码。