代码之家  ›  专栏  ›  技术社区  ›  Suma

动态访问Scala.js中的命名对象

  •  0
  • Suma  · 技术社区  · 6 年前

    我不想在任何地方列出它们,因为它们在我的应用程序中有数百个,而且它们经常被添加/删除。

    trait Res {
      def value: String
    }
    object A {
      def value = "A..."
    }
    object B {
      def value = "B..."
    }
    
    def loadAB(name: String): String {
      scala.scalajs.js.Dynamic.global.selectDynamic(name).asInstanceOf[Res].value
    }
    
    2 回复  |  直到 3 年前
        1
  •  3
  •   sjrd    6 年前

    您无法访问 object js.Dynamic.global ,因为默认情况下Scala.js不会在 global . 它只会放一些东西 具有 @JSExportTopLevel .

    @Simon Groenewolt提出了一个基于 @JSExportTopLevel公司 ,但在您的案例中,这是一个具有次优特性的黑客攻击。事实上,它将强制这些对象中的每一个在JavaScript全局范围内公开,这是不好的,因为它们可能被JavaScript篡改(或者篡改其他JavaScript库)。

    像这样的 全球的

    对于您的用例来说,更好的解决方案似乎是 Reflect 应用程序编程接口。特别是,看起来您希望能够加载 Res 他们的名字是什么 反映 给你,假设你注解 具有 @EnableReflectiveInstantiation

    package foo
    
    import scala.scalajs.reflect.Reflect
    import scala.scalajs.reflect.annotation.EnableReflectiveInstantiation
    
    @EnableReflectiveInstantiation
    trait Res {def value;}
    
    object A {def value = "A...";}
    object B {def value = "B...";}
    
    def loadAB(name: String): String {
      Reflect
        .lookupLoadableModuleClass(name + "$")
        .getOrElse(throw new Exception("hum, that as not found")
        .loadModule()
        .asInstanceOf[Res]
        .value
    }
    
    println(loadAB("foo.A"))
    

    注意,您需要使用对象的完全限定名。

        2
  •  1
  •   Simon Groenewolt    6 年前

    @JSExportTopLevel(<identifier>) 会有预期的效果吗?这是为了 exporting to JavaScript ,但会产生一个副作用,即在绑定时防止代码被丢弃。