JavaScript 中调用 Kotlin 方法实例详解
JavaScript中调用Kotlin方法实例详解
Kotlin编译器生成正常的JavaScript类,可以在JavaScript代码中自由地使用的函数和属性。不过,你应该记住一些微妙的事情。
用独立的JavaScript隔离声明
为了防止损坏全局对象,Kotlin创建一个包含当前模块中所有Kotlin声明的对象。所以如果你把模块命名为myModule,那么所有的声明都可以通过myModule对象在JavaScript中可用。例如:
funfoo()="Hello"
可以在JavaScript中这样调用:
alert(myModule.foo());
这不适用于当你将Kotlin模块编译为JavaScript模块时(关于这点的详细信息请参见JavaScript模块)。在这种情况下,不会有一个包装对象,而是将声明作为相应类型的JavaScript模块对外暴露。例如,对于CommonJS的场景,你应该写:
alert(require('myModule').foo());
包结构
Kotlin将其包结构暴露给JavaScript,因此除非你在根包中定义声明,否则必须在JavaScript中使用完整限定的名称。例如:
packagemy.qualified.packagename funfoo()="Hello"
可以在JavaScript中这样调用:
alert(myModule.my.qualified.packagename.foo());
@JsName注解
在某些情况下(例如为了支持重载),Kotlin编译器会修饰(mangle)JavaScript代码中生成的函数和属性的名称。要控制生成的名称,可以使用@JsName注解:
//模块“kjs” classPerson(valname:String){ funhello(){ println("Hello$name!") } @JsName("helloWithGreeting") funhello(greeting:String){ println("$greeting$name!") } }
现在,你可以通过以下方式在JavaScript中使用这个类:
varperson=newkjs.Person("Dmitry");//引用到模块“kjs” person.hello();//输出“HelloDmitry!” person.helloWithGreeting("Servus");//输出“ServusDmitry!”
如果我们没有指定@JsName注解,相应函数的名称会包含从函数签名计算而来的后缀,例如hello_61zpoe$。
请注意,Kotlin编译器不会对external声明应用这种修饰,因此你不必在其上使用@JsName。值得注意的另一个例子是从外部类继承的非外部类。在这种情况下,任何被覆盖的函数也不会被修饰。
@JsName的参数需要是一个常量字符串字面值,该字面值是一个有效的标识符。任何尝试将非标识符字符串传递给@JsName时,编译器都会报错。以下示例会产生编译期错误:
@JsName("newC()")//此处出错 externalfunnewC()
在JavaScript中表示Kotlin类型
- 除了kotlin.Long的Kotlin数字类型映射到JavaScriptNumber。
- kotlin.Char映射到JavaScriptNumber来表示字符代码。
- Kotlin在运行时无法区分数字类型(kotlin.Long除外),即以下代码能够工作:
funf(){ valx:Int=23 valy:Any=x println(yasFloat) }
- Kotlin保留了kotlin.Int、kotlin.Byte、kotlin.Short、kotlin.Char和kotlin.Long的溢出语义。
- JavaScript中没有64位整数,所以kotlin.Long没有映射到任何JavaScript对象,它是由一个Kotlin类模拟的。
- kotlin.String映射到JavaScriptString。
- kotlin.Any映射到JavaScriptObject(即newObject()、{}等)。
- kotlin.Array映射到JavaScriptArray。
- Kotlin集合(即List、Set、Map等)没有映射到任何特定的JavaScript类型。
- kotlin.Throwable映射到JavaScriptError。
- Kotlin在JavaScript中保留了惰性对象初始化。
- Kotlin不会在JavaScript中实现顶层属性的惰性初始化。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!