Kotlin-48.JavaScript呼叫Kotlin(Call Kotlin from JavaScript)

weixin_33850890發表於2017-08-08

官方文件: http://kotlinlang.org/docs/reference/js-to-kotlin-interop.html

在JS平臺上, kotlin程式碼會被Kotlin編譯器轉換成JavaScript類/函式/屬性;
因此在JavaScript程式碼中可以自由地呼叫kotlin程式碼, 然而還有一些細節需要注意!

1.獨立JavaScript物件隔離宣告(Isolating declarations in a separate JavaScript object)

為了防止損壞全域性物件,Kotlin建立一個模組(module)物件,它包含當前模組中所有Kotlin宣告;
如果kotlin模組名是myModule,那麼在JavaScript中可通過myModule物件使用kotlin宣告:
    // kotlin模組名是myModule
    fun foo() = "Hello"

    // 在JavaScript中呼叫, myModule是kotlin模組
    alert(myModule.foo());

當Kotlin模組(module)編譯為JavaScript模組(module)時,不適用於上述情況!
在此情況下,Kotlin不會建立的模組物件,而是將kotlin宣告作為相應型別的JavaScript模組,對外暴露:
    // myModule是kotlin模組,被編譯為JavaScript模組
    alert(require('myModule').foo());

2.包結構(Package structure)

Kotlin將其包結構暴露給JavaScript,
因此除非在根包中定義宣告, 否則必須在JavaScript中使用完整限定名,例如:
    // kotlin
    package my.qualified.packagename
    fun foo() = "Hello"

    // 在JavaScript中呼叫
    alert(myModule.my.qualified.packagename.foo());

3.@JsName註解(@JsName annotation)

在某些情況下(如為了支援過載),Kotlin編譯器會修改生成的JavaScript的函式名/屬性名,
使用@JsName註解,控制生成JavaScript的函式名/屬性名,:
    // kotlin模組"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註解,相應函式名會新增從函式簽名計算而來的字尾,例如hello_61zpoe$

注意: 1.Kotlin編譯器不會對external宣告使用@JsName註解修飾
      2.繼承自external類的非external類,被覆蓋的函式也不會被@JsName修飾!

@JsName引數是一個字串字面值常量(有效識別符號),如果將非識別符號字串傳遞給@JsName,編譯器會報錯:
    @JsName("new C()")  // 報錯, new C()不是字串字面值常量
    external fun newC()

4.在JavaScript中表示Kotlin型別(Representing Kotlin types in JavaScript)

1.Kotlin數字型別(kotlin.Long除外)都對映到JavaScript Number
2.kotlin.Char對映到JavaScript Number,表示字元碼
3.Kotlin在執行時無法區分數字型別(kotlin.Long除外),即以下程式碼能工作:
    fun f() {
        val x: Int = 23
        val y: Any = x
        println(y as Float)
    }
4.Kotlin保留了kotlin.Int, kotlin.Byte, kotlin.Short, kotlin.Char, kotlin.Long的溢位語義
5.JavaScript沒有64位整型數, 所以kotlin.Long沒有對映到任何JavaScript型別物件, 它由Kotlin類模擬
6.kotlin.String 對映到 JavaScript String
7.kotlin.Any 對映到 JavaScript Object (即new Object(), {}等)
8.kotlin.Array 對映到 JavaScript Array
9.Kotlin 集合(即List, Set, Map等)沒有對映到任何JavaScript型別
10.kotlin.Throwable 對映到 JavaScript Error
11.Kotlin 在JavaScript中保留了惰性物件初始化
12.Kotlin 在JavaScript中沒有實現頂層屬性的惰性初始化

簡書:http://www.jianshu.com/p/a377d6284f1c
CSDN部落格: http://blog.csdn.net/qq_32115439/article/details/75808450
GitHub部落格: http://lioil.win/2017/07/22/Kotlin-kotlinInJS.html
Coding部落格: http://c.lioil.win/2017/07/22/Kotlin-kotlinInJS.html

相關文章