当前位置:嗨网首页>书籍在线阅读

06-在JavaScript中调用Kotlin

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

15.2.2 在JavaScript中调用Kotlin

在JavaScript平台中,Kotlin代码会被Kotlin编译器编译成JavaScript类、函数或属性,因此在JavaScript代码中可以自由地调用Kotlin的函数和属性。

1.独立的JavaScript隔离声明

为了防止损坏全局对象,Kotlin创建了一个包含当前模块中所有Kotlin声明的模块(module)对象。如果Kotlin的模块名是myModule,那么在JavaScript中可以通过myModule对象来使用JavaScript声明。代码如下。

fun foo() = "Hello"  // Kotlin模块名是myModule

然后,可以在JavaScript中调用Kotlin的模块名。代码如下。

alert(myModule.foo());  //在JavaScript中调用Kotlin模块myModule

当把Kotlin模块编译为JavaScript模块时,直接使用上面的方式进行调用是不合适的。在此种情况下,Kotlin不会创建模块对象,而是将Kotlin声明对象作为相应类型的JavaScript模块对外暴露,此时,myModule作为Kotlin模块,会被编译为JavaScript模块。

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

2.包结构

Kotlin将其包结构暴露给JavaScript,除非在根包中定义声明,否则必须在 JavaScript中使用完整的名称。代码如下。

package my.qualified.packagename
fun foo() = "Hello"

在JavaScript中调用foo()时,需要使用完整的包结构名称。

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

3.@JsName注解

在某些情况下(如重载操作),Kotlin编译器会使用代码修饰JavaScript生成的函数和属性的名称,要控制生成的名称,需要使用@JsName注解。代码如下。

// Kotlin模块kjs
class Person(val name: String) {
      fun hello() {
          println("Hello $name!")
      }
    @JsName("helloWithGreeting")
    fun hello(greeting: String) {
         println("$greeting $name!")
    }
}

在JavaScript中可以按照下面的方式来调用Person类。

var person = new kjs.Person("Dmitry");   //引用模块kjs
person.hello();                          //输出Hello Dmitry!
person.helloWithGreeting("Servus");      //输出Servus Dmitry!

如果没有指定@JsName注解,则相应函数的名称会包含由函数签名计算而来的后缀,例如hello_61zpoe$。@JsName注解参数往往需要一个常量字符串字面值,该字面值是一个标识符。

需要注意的是,在external声明类和方法中不能使用@JsName注解。除此之外,从外部类继承的非外部类也是不能使用@JsName注解的。

4.在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.Int、kotlin.Byte、kotlin.Short、kotlin.Char和kotlin.Long的溢出语义。
  • 由于JavaScript中设有64位整数,因此kotlin.Long不可以映射到任何JavaScript对象中,它是由一个Kotlin类模拟的。
  • kotlin.String映射到JavaScript的String中。
  • kotlin.Any映射到JavaScript的Object中(new Object()、{}等)。
  • kotlin.Array映射到JavaScript 的Array中。
  • Kotlin集合(List、Set、Map等)无对应的JavaScript类型映射。
  • kotlin.Throwable 映射到JavaScript 的Error中。
  • Kotlin在JavaScript中保留了惰性对象初始化。
  • Kotlin不会在JavaScript中实现顶层属性的惰性初始化。

自Kotlin 1.1.50版本开始,将Kotlin原生数组转换到JavaScript时采用TypedArray。

  • kotlin.ByteArray、kotlin.ShortArray、kotlin.IntArray、kotlin.DoubleArra和kotlin.FloatArray会映射成JavaScript的Int8Array、Int16Array、 Int32Array、Float32Array和Float64Array。
  • kotlin.BooleanArray会映射成JavaScript中具有$type$ == "BooleanArray"属性的Int8Array。
  • kotlin.CharArray会映射成JavaScript中具有$type$ == "CharArray"属性的 UInt16Array。
  • kotlin.LongArray会映射成JavaScript中具有$type$ == "LongArray"属性的 kotlin.Long类型数组。