Scala.js 原生 Javascript 构造函数

标签 scala constructor scala.js

原生 JS 类型的 Scala.js 外观如下所示(来自 Three.js facade ):

@js.native
@JSName("THREE.Vector3")
class Vector3 extends Vector {
  def this(x: Double = js.native, y: Double = js.native, z: Double = js.native) = this()
  var x: Double = js.native
  var y: Double = js.native
  var z: Double = js.native

/* ... */
}

对应Javascript definition构造 Vector3 的函数是:

function Vector3( x, y, z ) {

    this.x = x || 0;
    this.y = y || 0;
    this.z = z || 0;

}

我已阅读有关 creating Scala.js facades 的文档,但是构造函数仅在那里被简单提及。外观中的代码在实际代码中工作得很好,但是我不确定定义是否正确以及它为什么以及如何工作。

  • 外观不允许参数构造函数存在。
  • 带参数的构造函数只调用无参数的构造函数。尽管如此,该对象似乎构造得很好,成员设置为传递的值。
  • 构造函数使用 js.native 作为所有参数的默认值。所有门面都应该这样定义构造函数吗?

特别是。第二点让我感到困惑。这怎么能行得通呢?在这三种情况下,我想知道为构造函数生成了哪些 JS 代码以及原因。

人们还可以想象一种不同的方式来编写外观。这样会更正确吗?

class Vector3(var x: Double = js.native, var y: Double = js.native, var z: Double = js.native) extends Vector {

/* ... */
}

最佳答案

这个定义是正确的。 JavaScript 构造函数的外观规则非常简单:当遇到诸如

之类的调用时
new C(arg1, ..., argN)

C 是一个 JavaScript 类,这会转换为

new Cconstr(arg1, ..., argN)

其中Cconstr是评估js.constructorOf[C]的结果。对于原生 JavaScript 类,js.constructorOf[C] 在全局范围内查找 C 的名称(或应用 @JSName@JSImport 规则)。具体来说,在您的示例中,诸如

之类的调用
new Vector3(3, 4, 5)

翻译为

new <global>.THREE.Vector3(3, 4, 5)

请特别注意,构造函数定义的主体是完全不相关的,因为调用站点直接调用 Three.js 库中的 JavaScript 代码。因此,语义规则完全忽略了 3-arg 构造函数调用 0-arg 构造函数并忽略其参数这一事实。该调用对于遵守 Scala 的类型检查规则是必要的,但在语义上无关。

同样,默认参数值的实际值在语义上也是无关的。它们的存在使得参数可选,但编译器会忽略它们的值。诸如这样的调用

new Vector3(3)

用 JavaScript 翻译为

new <global>.THREE.Vector3(3)

其中完全没有给出 yz 参数,让 JavaScript 来决定如何处理它们。

最后,您的替代定义:

class Vector3(var x: Double = js.native, var y: Double = js.native, var z: Double = js.native)

同样有效。它没有显式的 0-arg 构造函数,但也可以通过向构造函数提供 0 个参数来“访问”它,无论如何,构造函数都有 3 个可选参数。不过,这个定义当然更简洁,而且看起来更像 Scala 风格,所以我个人会这样定义它。但它并不比最初的更正确

关于Scala.js 原生 Javascript 构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41980986/

相关文章:

c++ - 在构造函数中,我可以获取成员的地址并相信它们将保持不变吗?

java - 在同一构造函数中使用调用构造函数

java - 对象在 Java 的构造函数中转义总是一个问题吗?

scala - 如何修复在intellij中使用binging.scala时出现的红色标记?

scala - 在 scalajs 的 scalatest 之前异步

scala - Scaja.js 浏览器支持

java - Spark SQL 失败,因为 "Constant pool has grown past JVM limit of 0xFFFF"

database - 在客户端和服务器之间共享的代码中表示 DB 实体的惯用方式

scala - Spark:使用Scala进行HBase批量加载

java - 我的 scala 应用程序中 val、lazy val 和 def 的神秘行为以及隐式转换