Передайте Scala. js экземпляр класса JavaScript, который вызовет метод вызова функции - PullRequest
1 голос
/ 22 января 2020

У меня есть простой 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.

1 Ответ

1 голос
/ 22 января 2020

В 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.

...