JavaScript中調用Kotlin

Kotlin 編譯器生成正常的 JavaScript 類,可以在 JavaScript 代碼中自由地使用的函數和屬性
。不過,你應該記住一些微妙的事情。

用獨立的 JavaScript 隔離聲明

爲了防止損壞全局對象,Kotlin 創建一個包含當前模塊中所有 Kotlin 聲明的對象
。所以如果你把模塊命名爲 myModule,那麼所有的聲明都可以
通過 myModule 對象在 JavaScript 中可用。例如:

fun foo() = "Hello"

可以在 JavaScript 中這樣調用:

alert(myModule.foo());

這不適用於當你將 Kotlin 模塊編譯爲 JavaScript 模塊時(關於這點的詳細信息請參見 JavaScript 模塊)。
在這種情況下,不會有一個包裝對象,而是將聲明作爲相應類型的 JavaScript 模塊對外暴露。例如,
對於 CommonJS 的場景,你應該寫:

alert(require('myModule').foo());

包結構

Kotlin 將其包結構暴露給 JavaScript,因此除非你在根包中定義聲明,
否則必須在 JavaScript 中使用完整限定的名稱。例如:

package my.qualified.packagename

fun foo() = "Hello"

可以在 JavaScript 中這樣調用:

alert(myModule.my.qualified.packagename.foo());

[@JsName](https://github.com/JsName "@JsName") 註解

在某些情況下(例如爲了支持重載),Kotlin 編譯器會修飾(mangle) JavaScript 代碼中生成的函數和屬性
的名稱。要控制生成的名稱,可以使用 [@JsName](https://github.com/JsName "@JsName") 註解:

// 模塊「kjs」
class Person(val name: String) {
    fun hello() {
        println("Hello $name!")
    }

    @JsName("helloWithGreeting")
    fun hello(greeting: String) {
        println("$greeting $name!")
    }
}

現在,你可以通過以下方式在 JavaScript 中使用這個類:

var person = new kjs.Person("Dmitry");   // 引用到模塊「kjs」
person.hello();                          // 輸出「Hello Dmitry!」
person.helloWithGreeting("Servus");      // 輸出「Servus Dmitry!」

如果我們沒有指定 [@JsName](https://github.com/JsName "@JsName") 註解,相應函數的名稱會包含
從函數簽名計算而來的後綴,例如 hello_61zpoe$

請注意,Kotlin 編譯器不會對 external 聲明應用這種修飾,因此你不必在其上
使用 [@JsName](https://github.com/JsName "@JsName")。 值得注意的另一個例子是從外部類繼承的非外部類。
在這種情況下,任何被覆蓋的函數也不會被修飾。

[@JsName](https://github.com/JsName "@JsName") 的參數需要是一個常量字符串字面值,該字面值是一個有效的標識符。
任何嘗試將非標識符字符串傳遞給 [@JsName](https://github.com/JsName "@JsName") 時,編譯器都會報錯。
以下示例會產生編譯期錯誤:

@JsName("new C()")   // 此處出錯
external fun newC()

在 JavaScript 中表示 Kotlin 類型

  • 除了 kotlin.Long 的 Kotlin 數字類型映射到 JavaScript Number。

  • kotlin.Char 映射到 JavaScript Number 來表示字符代碼。

  • Kotlin 在運行時無法區分數字類型(kotlin.Long 除外),即以下代碼能夠工作:

    fun f() {
        val x: Int = 23
        val y: Any = x
        println(y as Float)
    }
  • Kotlin 保留了 kotlin.Intkotlin.Bytekotlin.Shortkotlin.Charkotlin.Long 的溢出語義。

  • JavaScript 中沒有 64 位整數,所以 kotlin.Long 沒有映射到任何 JavaScript 對象,
    它是由一個 Kotlin 類模擬的。

  • kotlin.String 映射到 JavaScript String。

  • kotlin.Any 映射到 JavaScript Object(即 new Object(){} 等)。

  • kotlin.Array 映射到 JavaScript Array。

  • Kotlin 集合(即 ListSetMap 等)沒有映射到任何特定的 JavaScript 類型。

  • kotlin.Throwable 映射到 JavaScript Error。

  • Kotlin 在 JavaScript 中保留了惰性對象初始化。

  • Kotlin 不會在 JavaScript 中實現頂層屬性的惰性初始化。