运行以下编译成scala-js版本0.8.0的Scala代码,我收到以下错误:
An undefined behavior was detected: undefined is not an instance of java.lang.String
trait MyDataType extends js.Any {
var wordy: String = js.native
}
// This usually comes from the backend.
val dataStruct = js.Dynamic.literal().asInstanceOf[MyDataType]
val isWordy = dataStruct.wordy
经过调查,上面的代码编译为:
var dataStruct = {};
var isWordy = $as_T(dataStruct["wordy"]); // Line causing problem.
显然正是由于这个$as_T
造成了这个麻烦。
如何确保上面的代码未经检查?
编辑我找到了一种不太优雅的解决方法。
val isWordy = dataStruct.asInstanceOf[js.Dynamic].wordy
但是,为什么这个$as_T
?
答案 0 :(得分:4)
我认为这个问题是错误的。说asInstanceOf[MyDataType]
是告诉 Scala来检查它。这几乎正是这意味着什么。当它进行类型检查时,它会完全断言:你告诉Scala.js这个是 MyDataType的一个实例,因此它必须完全符合MyDataType。
因此,如果您真的不希望对其进行类型检查,那么正确的解决方案就是放弃asInstanceOf
。那时它是一个JavaScript动态,你可以用它做任何事情。
(或者您需要在wordy
内为literal()
分配内容,以便 实际上是MyDataType
。)
换句话说,Scala.js有两个世界:无类型的JavaScript和强类型的Scala。两者都运作良好,但在任何时候你都必须选择你正在经营的那个。
ETA:有点理由。强类型语言的重点在于代码中的所有内容都确切地知道该类型的结构是什么 - 这样,您只需要担心代码中的错误,而不是糟糕的数据。这就是为什么asInstanceOf
需要难以理解的原因:因此,如果将值传递给某个期望MyDataType
的函数,它肯定知道wordy
已定义。