Kotlin言語でJavaScriptメソッドの実例を呼び出します。

3930 ワード

Kotlin言語でJavaScriptメソッドの実例を呼び出します。
KotlinはJavaプラットフォームと簡単に相互操作できるように設計されています。Java類はKotlin類とみなされ、JavaはKotlin類をJava類とも見なしています。しかし、JavaScriptは動的なタイプの言語であり、コンパイル中にタイプを確認しないことを意味しています。動態タイプを通じて、JavaScriptと自由にコミュニケーションができますが、Kotlinタイプのシステムの威力の全てが欲しいなら、JavaScriptライブラリのためにKotlinヘッダファイルを作成することができます。
インラインJavaScript
js関数を使って、JavaScriptコードの一部をKotlinコードに埋め込むことができます。たとえば:

fun jsTypeOf(o: Any): String {
 return js("typeof o")
}
jsのパラメータは文字列の定数でなければなりません。したがって、以下のコードは正しくないです。

fun jsTypeOf(o: Any): String {
 return js(getTypeof() + " o") //     
}
fun getTypeof() = "typeof"
external修饰符
Kotlinにある声明は純粋なJavaScriptで書かれていると伝えたいのですが、external修繕符で表記してください。コンパイラがこのような声明を見たとき、対応するクラス、関数または属性の実装が開発者によって提供されると仮定しているので、声明からJavaScriptコードを生成しようとはしない。これはあなたがexternal声明の内容のコード体を省略すべきという意味です。たとえば:

external fun alert(message: Any?): Unit

external class Node {
 val firstChild: Node

 fun append(child: Node): Node

 fun removeChild(child: Node): Node

 //   
}
external val window: Window
ネストされた声明はexternal修飾子を継承します。すなわちNodeクラスでは、メンバー関数と属性の前にexternalを置いていません。
external修飾子はパッケージステートメントでのみ使用できます。あなたは非externalクラスのメンバーを宣言することができません。
 宣言クラスの(静的)メンバー
JavaScriptでは、プロトタイプまたはクラス自体にメンバーを定義することができます。すなわち、

function MyClass() {
}
MyClass.sharedMember = function() { /*    */ };
MyClass.prototype.ownMember = function() { /*    */ };
Kotlinにはこのような文法がありません。しかし、Kotlinの中には連れがいます。Kotlinは特殊な方法でexternal類のバックグラウンドオブジェクトを処理します。期待の代わりに、バックグラウンドオブジェクトのメンバーがこのクラスのメンバーであると仮定します。上記の例からのMyClassを説明するには、このように書いてもいいです。

external class MyClass {
 companion object {
  fun sharedMember()
 }

 fun ownMember()
}

オプションのパラメータを宣言
外部関数の一つにはオプションのパラメータがあります。JavaScriptが実際にどのようにこれらのパラメータのデフォルト値を計算するかはKotlinでは知られていないので、Kotlinでは通常の構文でこれらのパラメータを宣言することは不可能です。以下の文法を使うべきです。

external fun myFunWithOptionalArgs(x: Int,
 y: String = definedExternally,
 z: Long = definedExternally)
これは、必要な引数とオプションの二つのパラメータを使用して、myFun WithOptionalArgsを呼び出すことができることを意味します。これらのデフォルト値はいくつかのJavaScriptコードから計算されます。
JavaScriptクラスを拡張
JavaScriptクラスを手軽に広げることができます。externalクラスを定義し、非externalクラスで拡張します。たとえば:

external open class HTMLElement : Element() {
 /*    */
}

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

いくつかの制限があります
外部ベースクラスの関数を署名して再ロードすると、派生クラスで上書きできません。
デフォルトのパラメータを使用する関数を上書きできません。
外部クラスではなく外部クラスを拡張することはできません。
インターフェース
JavaScriptはインターフェースの概念がありません。関数がそのパラメータがfooおよびbar法をサポートすることを期待する場合は,これらの方法を実際に持つオブジェクトを伝えるだけでよい。静的タイプのKotlinに対しては、この点をインターフェースを使用して表現することができます。例えば、

external interface HasFooAndBar {
 fun foo()

 fun bar()
}

external fun myFunction(p: HasFooAndBar)
外部インターフェースのもう一つの使用シーンは、設定対象を説明するものである。たとえば:

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")
  }
 })
}

外部インターフェースにはいくつかの制限があります。
これらはis検査の右側では使えません。
as変換は常に外部インターフェースに成功します。
それらは特定のタイプのパラメータとして伝達できない。
これらはクラスの額面表現(I:class)では使えません。
読んでくれてありがとうございます。みなさんのご協力をお願いします。ありがとうございます。