native JS typeとnon-native JS typeという概念がある。
それぞれのtypeのtraitが存在し、そもそものScalaのtraitに加えて、
- scala trait (勝手に呼んでいる)
- native JS trait
- non-native JS trait
の三種類が存在する。
native JS trait
native JSはJavaScriptで実装されたライブラリを読み込んで使う場合に使う。
いくら書いてもJavaScriptコードは生成されない。
Scala.js上でインスタンスをつくるにはjs.Dynamic.literal
を使用する。
facadeを書くのに使う。
例
@js.native
trait Point extends js.Object {
val x: Int
val y: Int
}
val point = js.Dynamic.literal(x = 1, y = 2).asInstanceOf[Point]
js.Dynamic.global.console.log(p) // => {x: 1, y: 2}
js.Any
の派生をミックスインしていて、@js.native
が付与されてるのがポイント。
より詳細はこちらに。
https://www.scala-js.org/doc/interoperability/facade-types.html
non-native JS trait
Scala.jsで実装したJSのコード。
classにミックスインしたり、無名クラスでインスタンスが作れる。
JavaScriptのオブジェクトとして利用可能
メソッドは定義できない。
例
trait Point extends js.Object {
val x: Int
val y: Int
}
val point = new Point {
override val x: Int = 1
override val y: Int = 2
}
js.Dynamic.global.console.log(point) // => { x: 1, x: 2}
利用には、
@ScalaJSDefined
アノテーションをつけるか、sbtに以下のコードを貼り付ける必要がある。
scalacOptions += "-P:scalajs:sjsDefinedByDefault"
native JSに比較して、安全にインスタンスが作成できる。
より詳細はこちらに。
https://www.scala-js.org/doc/interoperability/sjs-defined-js-classes.html
Scala trait
普通のScalaのトレイト
何らかのコードが生成される。
普通に使える。
定義したフィールドがプロパティと一致しないため、JavaScriptのオブジェクトとしては使えない。
trait Point {
val x: Int
val y: Int
}
val point = new Point {
override x: Int = 1
override y: Int = 2
}
js.Dynamic.global.console.log(p.asInstanceOf[js.Any]) // => $c_LPointScala { 'x$1': 1, 'y$1': 2 }
println(p.x) // => 1
プロパティはフィールド名と一致しない。
代わりにgetterが定義されてるのを確認できる。
JSのライブラリに渡して安全に動くとは限らない。
まとめ
native JS | non-native JS | Scala | |
---|---|---|---|
インスタンス作成 | js.Dynamic.literalで | できる | できる |
メソッド定義 | インターフェースのみ実装は生成されない | できない(抽象クラスでできる) | できる |
js Objectとして使用 | できる | できる | できるがおすすめできない |