scala - scala.js 1.0 中的@JSGlobalScope(JavaScriptException、ReferenceError、var 未定义)
问题描述
从 scala.js 迁移0.6.x
到之后1.0
,我得到了一些与@JSGlobalScope
损坏相关的代码。
我的用例是这样的:
- 有一个 3rd-party 库,它期望将一些全局变量设置为函数
- 加载并准备好后,它会调用此函数(按名称)
- 我在 scala.js 的全局范围内设置了这个函数
代码如下所示:
@js.native
@JSGlobalScope
object Globals extends js.Object {
var callbackFunctionFor3rdPartyLib: js.Function0[Unit] = js.native
}
然后我像这样设置这个变量:
Globals.callbackFunctionFor3rdPartyLib = () => {
// do things
}
然后我将脚本添加到 DOM 中。
这与 scala.js 一起使用0.6.x
,但1.0
我遇到了如下异常:
scala.scalajs.js.JavaScriptException: ReferenceError: callbackFunctionFor3rdPartyLib is not defined
在1.0.0 的更新日志中有一个“重大更改”部分提到了这一点:
访问未声明的成员会导致抛出 ReferenceError ...
js.Dynamic.global.globalVarThatDoesNotExist = 42
以前会创建所述全局变量。在 Scala.js 1.x 中,它还会引发 ReferenceError。
我的问题是:
在 scala.js 中做这样的事情(创建一个新的全局变量)的正确方法是什么1.0
?
解决方案
如果您知道您将始终处于浏览器上下文中,则可以使用@JSGlobal("window")
而不是@JSGlobalScope
on your Globals
,这将等效于window.myGlobalVarFor3rdPartyLib
在 JS 中执行。所以这会奏效。
@js.native
@JSGlobal("window")
object Globals extends js.Object {
var callbackFunctionFor3rdPartyLib: js.Function0[Unit] = js.native
}
如果不是,但您使用的是脚本(所以不是 CommonJS 也不是 ES 模块),最好的办法是实际使用
object Globals {
@JSExportTopLevel("myGlobalVarFor3rdPartyLib")
var foo: js.Function[Unit] = ...
}
请注意,这Globals
是一个普通的 Scala 对象,而不是 JS 对象。
在脚本顶部@JSExportTopLevel
创建一个顶级var myGlobalVarFor3rdPartyLib
,然后分配Globals.foo
也将分配该顶级var
。
如果您不使用脚本也不知道您将始终在浏览器中,那么您需要自己找出全局对象。Scala.js 0.6.x 尝试为您执行此操作,但可能会失败,因此我们不再执行此操作。您至少可以按照文档中js.special.fileLevelThis
的“说明”来重现 Scala.js 0.6.x 所做的事情。我在这里重复说明:
使用此值应该很少见,并且主要限于编写检测全局对象是什么的代码。例如,一个典型的检测代码——如果我们不需要担心 ES 模块——看起来像:
val globalObject = { import js.Dynamic.{global => g} if (js.typeOf(g.global) != "undefined" && (g.global.Object eq g.Object)) { // Node.js environment detected g.global } else { // In all other well-known environment, we can use the global `this` js.special.fileLevelThis } }
请注意,上面的代码并不全面,因为在 JavaScript 环境中,全局对象可能无法通过
global
或获取this
。如果您的代码需要在这样的环境中运行,则由您决定使用适当的检测程序。
推荐阅读
- mongodb - Intellij/Datagrip 通过旧版 uuid 查询 mongo
- c++ - 不知道为什么我在使用 cin 和 getline 时遇到 C++ 错误
- php - 从文件读取时格式错误的 JSON
- python - 有没有办法在 sklearn 中存储管道阶段?
- decimal-point - 平原三点定向运算的数值稳定性
- sql - 如何为红移中字符串的唯一计数百分比?
- c - 这些示例中星号的含义
- maven - Maven跳过模块发布
- ios - Swift:打开/创建 SQLite 数据库适用于模拟器,但不适用于 iPhone
- python - 所以我有这个正在使用的文本文件,我想将其中的信息用于我的停车系统