Kotlin-47.Kotlin調用JavaScript(Call JavaScript from Kotlin)

官方文檔: http://kotlinlang.org/docs/reference/js-interop.html

1.Kotlin調用JavaScript(Calling JavaScript from Kotlin)

Kotlin被設計能夠與Java平臺輕鬆互操作,kotlin可將Java類轉爲Kotlin類,Java也將Kotlin類轉爲Java類!
但JavaScript是一種動態類型語言,意味着不會在編譯期檢查類型,可以在Kotlin中與JavaScript自由交流,
但如果想用Kotlin類型系統全部功能,需要在JavaScript庫創建Kotlin頭文件!

2.內聯JavaScript(Inline JavaScript)

可用js("JavaScript代碼")函數將JavaScript代碼嵌入到Kotlin代碼中:
    fun jsTypeOf(o: Any): String {
        return js("typeof o")
    }

js("...")函數參數必須是字符串常量,因此以下代碼錯誤:
    fun jsTypeOf(o: Any): String {
        return js(getTypeof() + " o") // 此處報錯
    }
    fun getTypeof() = "typeof"

3.external修飾符(external modifier)

用external修飾符來標記,通知Kotlin某個聲明是用純JavaScript編寫!
編譯器會認爲被修飾的類/函數/屬性的具體實現由開發人員提供,不會在聲明中生成任何JavaScript代碼,
因此external聲明應該沒有代碼體內容,例如:
    // 以下聲明都沒有代碼體,具體代碼由JavaScript提供
    external fun alert(message: Any?): Unit
    external val window: Window
    external class Node {
        //external修飾符會被繼承,即Node類的成員函數和屬性前不需要添加external
        val firstChild: Node

        fun append(child: Node): Node

        fun removeChild(child: Node): Node
    }
提示: external修飾符只允許在包級聲明中使用(package-level)

4.聲明類的靜態成員(Declaring static members)

在JavaScript中可以在原型(prototype)或者類(class)本身上定義成員:
    function MyClass() {
    }

    MyClass.sharedMember = function() {            
    };

    MyClass.prototype.ownMember = function() {            
    };

Kotlin沒有這樣的語法,但Kotlin有伴生對象(companion object),假定伴生對象的成員就是該類自身的成員:
    external class MyClass {
        companion object {
            fun sharedMember()
        }

        fun ownMember()
    }

5.聲明可選參數(Declaring optional parameters)

一個外部(external)函數有可選參數,但Kotlin無法知道JavaScript是如何計算這些參數的默認值,
因此在Kotlin中不能使用常用語法聲明這些默認參數,應該使用以下語法:
    external fun myFunWithOptionalArgs(x: Int,
        y: String = definedExternally,
        z: Long = definedExternally)
    // y, z 參數默認值由JavaScript代碼算出(definedExternally在外部定義)

6.擴展JavaScript類(Extending JavaScript class)

擴展JavaScript類很容易,因爲它們都是Kotlin類,只需定義一個external類,並用非external類擴展,例如:
    external open class HTMLElement : Element() {

    }

    class CustomElement : HTMLElement() {
        fun foo() {
            alert("bar")
        }
    }

一些限制:
    1.當一個外部(external)基類的函數被簽名重載時,不能在派生類(子類)中覆蓋它;
    2.不能覆蓋一個使用默認參數的函數;
    注意: 不能用external類擴展非external類!

7.external接口(external interface)

JavaScript沒有接口的概念,當函數期望其參數支持方法時,只能傳遞含有這些方法的對象;
對於靜態類型的Kotlin,可以使用外部(external)接口,例如:
    external interface HasFooAndBar {
        fun foo()

        fun bar()
    }

    // 傳遞含有foo和bar方法的HasFooAndBar
    external fun myFunction(p: HasFooAndBar)

外部(external)接口的另一個使用場景是描述設置對象(settings objects),例如:
    external interface JQueryAjaxSettings {
        var async: Boolean
        var cache: Boolean
        var complete: (JQueryXHR, String) -> Unit
    }

    fun JQueryAjaxSettings(): JQueryAjaxSettings = js("{}")

    external class JQuery {
        companion object {
            fun get(settings: JQueryAjaxSettings): JQueryXHR
        }
    }

    fun sendQuery() {
        JQuery.get(JQueryAjaxSettings().apply {
            complete = { (xhr, data) ->
                window.alert("Request complete")
            }
        })
    }

外部(external)接口的一些限制:
    1.它們不能在is檢查操作符的右側使用;
    2.as轉換爲external接口總是成功(在編譯時產生警告);
    3.它們不能作爲具體化類型參數(reified type)傳遞;
    4.它們不能用在類的字面值(literal)表達式(例如 I::class)中;

簡書:http://www.jianshu.com/p/d7259e03bd72
CSDN博客: http://blog.csdn.net/qq_32115439/article/details/75675844
GitHub博客: http://lioil.win/2017/07/21/Kotlin-jsInKotlin.html
Coding博客: http://c.lioil.win/2017/07/21/Kotlin-jsInKotlin.html

發佈了156 篇原創文章 · 獲贊 38 · 訪問量 27萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章