首页 > 解决方案 > 将 Scala.js 类实例传递给将调用函数调用方法的 JavaScript

问题描述

我有一个简单的 Scala.js 类(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()

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

如何为这种情况构建一个合适的类?

更新:

这是一些基于@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 库。

标签: scala.js

解决方案


在 JavaScript 中,调用 likemyfoo()有效的唯一方法是 ifmyfoo创建为函数值。此外,要使其myfoo.bar()工作,必须在创建函数值后对其进行修补。没有办法(除了代理,它完全是另一种野兽)首先创建myfoo一个对象,无论是否来自一个类,并让它回答myfoo().

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

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

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


推荐阅读