【问题标题】:Pass Scala.js class instance to JavaScript that will invoke the function call method将 Scala.js 类实例传递给将调用函数调用方法的 JavaScript
【发布时间】:2020-01-22 23:51:49
【问题描述】:

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

当然,这不起作用,因为我无法在 Foo 上定义 apply 方法,因为它派生自 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


    【解决方案1】:

    在 JavaScript 中,像 myfoo() 这样的调用有效的唯一方法是 myfoo创建为函数值。此外,要使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 代码。

    【讨论】:

    • 谢谢你——我真的很想弄清楚这一点。我正在处理外观,只是为了确保我理解正确,在这种情况下无法强制执行任何静态类型,因为您必须将对象零碎地构造为js.Dynamic(这是相应的 JavaScript 代码所做的更多)或更少)
    • 当然我的实际用例有更多的要求,需要存储一些来自bar调用的数据,供以后apply调用使用。除了像 JavaScript 这样基本上使用 js.Dynamic 之外,在这种情况下是否有可能?
    • 要存储数据,您可以使用 myfoo.someData = "whatever"myfoo 上动态存储字段(在这种情况下,您可能必须将 myfoo 声明为 lazy val 并使用显式类型:@987654336 @)。或者你可以简单地为myfoo 定义之上的数据声明vars,并使用来自applybarvars。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-29
    • 2015-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-27
    相关资源
    最近更新 更多