Scala.js 本机 Javascript 构造函数
Scala.js native Javascript constructors
Scala.js 原生 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
/* ... */
}
构造Vector3
的函数对应的Javascript definition为:
function Vector3( x, y, z ) {
this.x = x || 0;
this.y = y || 0;
this.z = z || 0;
}
我已经阅读了有关 creating Scala.js facades 的文档,但是那里只是简要地提到了构造函数。 Facade 中的代码在实际代码中工作正常,但是我不确定定义是否正确以及为什么以及如何工作。
- 外观不允许参数构造函数存在。
- 带参数的构造函数只是调用一个无参数的构造函数。对象似乎构造得很好,成员设置为传递的值。
- 构造函数使用
js.native
作为所有参数的默认值。所有外观都应该这样定义构造函数吗?
Esp。第二点让我感到困惑。这怎么行?在这三种情况下,我想知道为构造函数生成了哪些 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
是一个JavaScriptclass,这转化为
new Cconstr(arg1, ..., argN)
其中 Cconstr
是计算 js.constructorOf[C]
的结果。对于本机 JavaScript class,js.constructorOf[C]
在全局范围内查找 C
的名称(或应用 @JSName
或 @JSImport
规则)。具体来说,在您的示例中,调用
new Vector3(3, 4, 5)
转换为
new <global>.THREE.Vector3(3, 4, 5)
请特别注意,构造函数定义的 body 完全无关,因为调用站点直接调用 Three.js 中的 JavaScript 代码图书馆。因此,语义规则完全忽略了 3-arg 构造函数调用 0-arg 构造函数并忽略其参数的事实。该调用对于遵守 Scala 的类型检查规则是必要的,但在语义上无关紧要。
同样,默认参数值的实际值在语义上是无关的。它们的存在使参数成为可选参数,但编译器会忽略它们的值。调用如
new Vector3(3)
翻译成JavaScript到
new <global>.THREE.Vector3(3)
其中 y
和 z
参数完全没有给出,留给 JavaScript 来决定如何处理它们。
最后,您的替代定义:
class Vector3(var x: Double = js.native, var y: Double = js.native, var z: Double = js.native)
同样有效。它没有明确的 0-arg 构造函数,但它也可以是 "accessed" 通过给构造函数 0 个参数,它有 3 个可选参数。不过,这个定义当然更简洁,看起来更 Scala-esque,所以我个人会这样定义。但它并不比最初的更正确。
Scala.js 原生 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
/* ... */
}
构造Vector3
的函数对应的Javascript definition为:
function Vector3( x, y, z ) {
this.x = x || 0;
this.y = y || 0;
this.z = z || 0;
}
我已经阅读了有关 creating Scala.js facades 的文档,但是那里只是简要地提到了构造函数。 Facade 中的代码在实际代码中工作正常,但是我不确定定义是否正确以及为什么以及如何工作。
- 外观不允许参数构造函数存在。
- 带参数的构造函数只是调用一个无参数的构造函数。对象似乎构造得很好,成员设置为传递的值。
- 构造函数使用
js.native
作为所有参数的默认值。所有外观都应该这样定义构造函数吗?
Esp。第二点让我感到困惑。这怎么行?在这三种情况下,我想知道为构造函数生成了哪些 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
是一个JavaScriptclass,这转化为
new Cconstr(arg1, ..., argN)
其中 Cconstr
是计算 js.constructorOf[C]
的结果。对于本机 JavaScript class,js.constructorOf[C]
在全局范围内查找 C
的名称(或应用 @JSName
或 @JSImport
规则)。具体来说,在您的示例中,调用
new Vector3(3, 4, 5)
转换为
new <global>.THREE.Vector3(3, 4, 5)
请特别注意,构造函数定义的 body 完全无关,因为调用站点直接调用 Three.js 中的 JavaScript 代码图书馆。因此,语义规则完全忽略了 3-arg 构造函数调用 0-arg 构造函数并忽略其参数的事实。该调用对于遵守 Scala 的类型检查规则是必要的,但在语义上无关紧要。
同样,默认参数值的实际值在语义上是无关的。它们的存在使参数成为可选参数,但编译器会忽略它们的值。调用如
new Vector3(3)
翻译成JavaScript到
new <global>.THREE.Vector3(3)
其中 y
和 z
参数完全没有给出,留给 JavaScript 来决定如何处理它们。
最后,您的替代定义:
class Vector3(var x: Double = js.native, var y: Double = js.native, var z: Double = js.native)
同样有效。它没有明确的 0-arg 构造函数,但它也可以是 "accessed" 通过给构造函数 0 个参数,它有 3 个可选参数。不过,这个定义当然更简洁,看起来更 Scala-esque,所以我个人会这样定义。但它并不比最初的更正确。