【问题标题】:Dynamic access to named objects in Scala.js在Scala.js中的命名对象的动态访问
【发布时间】:2019-02-26 05:38:35
【问题描述】:

我想动态访问我的 Scala.js 项目中的一些对象。我想我也许可以使用 Dynamic 来完成这项工作,但是目前 fastOptJS / fullOptJS 步骤正在丢弃它们。有什么方法(注释?)我可以根据需要标记它们,在优化过程中永远不会被丢弃?

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

例子:

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
}

【问题讨论】:

    标签: scala scala.js


    【解决方案1】:

    您无法通过js.Dynamic.global 访问Scala.js 中定义的objects,因为默认情况下Scala.js 不会在global 中放入任何内容。它只会将带有@JSExportTopLevel 的东西导出

    @Simon Groenewolt 建议了一个基于 @JSExportTopLevel 的解决方案,但在您的情况下,这是一个具有次优属性的 hack。实际上,它会强制将这些对象中的每一个都暴露在 JavaScript 全局范围内,这是不好的,因为它们可能会被 JavaScript 篡改(或篡改其他 JavaScript 库)。

    此外,如果您(或您的家属)发出 CommonJS 模块,该 hack 将停止运行。它也将在 Scala.js 1.x 中不再工作这样,因为不再允许从 global 进行动态选择(您必须事先自己动态查找全局对象)。

    Reflect API 似乎为您的用例提供了更好的解决方案。特别是,您似乎希望能够加载扩展 Resobjects 给定他们的名字,这正是 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"))
    

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

    【讨论】:

    • 比我的更好的解决方案! (关于它不适用于 javascript 模块的一个好点)
    【解决方案2】:

    也许用@JSExportTopLevel(<identifier>) 注释它们会产生预期的效果?这适用于exporting to JavaScript,但会产生副作用,即在捆绑时防止代码被丢弃。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-13
      • 1970-01-01
      • 1970-01-01
      • 2017-09-09
      • 2018-06-12
      相关资源
      最近更新 更多