我的Scala.js项目中有一些对象我想动态访问。我想我可以使用Dynamic来使它工作,但是目前fastOptJS / fullOptJS步骤正在丢弃它们。有什么方法(注释?)我可以将它们标记为必需的,而在优化过程中永不丢弃?
我不想在任何地方列出它们,因为它们在我的应用程序中有数百个,并且经常被添加/删除。
示例:
trait Res {def value;}
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
}
答案 0 :(得分:2)
您无法通过object
访问Scala.js中定义的js.Dynamic.global
,因为默认情况下Scala.js不会在global
中放置任何内容。它只将带有@JSExportTopLevel
的内容导出到其中。
@Simon Groenewolt建议了基于@JSExportTopLevel
的解决方案,但这是您的情况下性能欠佳的黑客。确实,这将迫使这些对象中的每个对象都在JavaScript全局范围内公开,这不好,因为它们可能会被JavaScript篡改(或篡改其他JavaScript库)。
此外,如果您(或您的家属)发出CommonJS模块,则该黑客将停止运行。在Scala.js 1.x中,如此也将不再起作用,因为将不再允许从global
进行动态选择(您必须事先自己动态查找全局对象) )。
针对您的用例的更好解决方案似乎是Reflect
API。尤其是,您似乎希望能够加载给定名称的object
扩展了Res
的{{1}},假设您注释了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"))
请注意,您需要使用对象的完全限定名称。
答案 1 :(得分:1)
也许用@JSExportTopLevel(<identifier>)
注释它们会达到预期的效果吗?这是针对exporting to JavaScript的,但具有防止捆绑时丢弃代码的副作用。