Kotlin 语言中调用 JavaScript 方法实例详解
Kotlin语言中调用JavaScript方法实例详解
Kotlin已被设计为能够与Java平台轻松互操作。它将Java类视为Kotlin类,并且Java也将Kotlin类视为Java类。但是,JavaScript是一种动态类型语言,这意味着它不会在编译期检查类型。你可以通过动态类型在Kotlin中自由地与JavaScript交流,但是如果你想要Kotlin类型系统的全部威力,你可以为JavaScript库创建Kotlin头文件。
内联JavaScript
你可以使用js("……")函数将一些JavaScript代码嵌入到Kotlin代码中。例如:
funjsTypeOf(o:Any):String{ returnjs("typeofo") }
js的参数必须是字符串常量。因此,以下代码是不正确的:
funjsTypeOf(o:Any):String{ returnjs(getTypeof()+"o")//此处报错 } fungetTypeof()="typeof"
external修饰符
要告诉Kotlin某个声明是用纯JavaScript编写的,你应该用external修饰符来标记它。当编译器看到这样的声明时,它假定相应类、函数或属性的实现由开发人员提供,因此不会尝试从声明中生成任何JavaScript代码。这意味着你应该省略external声明内容的代码体。例如:
externalfunalert(message:Any?):Unit externalclassNode{ valfirstChild:Node funappend(child:Node):Node funremoveChild(child:Node):Node //等等 } externalvalwindow:Window
请注意,嵌套的声明会继承external修饰符,即在Node类中,我们在成员函数和属性之前并不放置external。
external修饰符只允许在包级声明中使用。你不能声明一个非external类的external成员。
声明类的(静态)成员
在JavaScript中,你可以在原型或者类本身上定义成员。即:
functionMyClass(){ } MyClass.sharedMember=function(){/*实现*/}; MyClass.prototype.ownMember=function(){/*实现*/};
Kotlin中没有这样的语法。然而,在Kotlin中我们有伴生(companion)对象。Kotlin以特殊的方式处理external类的伴生对象:替代期待一个对象的是,它假定伴生对象的成员就是该类自身的成员。要描述来自上例中的MyClass,你可以这样写:
externalclassMyClass{ companionobject{ funsharedMember() } funownMember() }
声明可选参数
一个外部函数可以有可选参数。JavaScript实现实际上如何计算这些参数的默认值,是Kotlin所不知道的,因此在Kotlin中不可能使用通常的语法声明这些参数。你应该使用以下语法:
externalfunmyFunWithOptionalArgs(x:Int, y:String=definedExternally, z:Long=definedExternally)
这意味着你可以使用一个必需参数和两个可选参数来调用myFunWithOptionalArgs(它们的默认值由一些JavaScript代码算出)。
扩展JavaScript类
你可以轻松扩展JavaScript类,因为它们是Kotlin类。只需定义一个external类并用非external类扩展它。例如:
externalopenclassHTMLElement:Element(){ /*成员*/ } classCustomElement:HTMLElement(){ funfoo(){ alert("bar") } }
有一些限制:
当一个外部基类的函数被签名重载时,不能在派生类中覆盖它。
不能覆盖一个使用默认参数的函数。
请注意,你无法用外部类扩展非外部类。
external接口
JavaScript没有接口的概念。当函数期望其参数支持foo和bar方法时,只需传递实际具有这些方法的对象。对于静态类型的Kotlin,你可以使用接口来表达这点,例如:
externalinterfaceHasFooAndBar{ funfoo() funbar() } externalfunmyFunction(p:HasFooAndBar)
外部接口的另一个使用场景是描述设置对象。例如:
externalinterfaceJQueryAjaxSettings{ varasync:Boolean varcache:Boolean varcomplete:(JQueryXHR,String)->Unit //等等 } funJQueryAjaxSettings():JQueryAjaxSettings=js("{}") externalclassJQuery{ companionobject{ funget(settings:JQueryAjaxSettings):JQueryXHR } } funsendQuery(){ JQuery.get(JQueryAjaxSettings().apply{ complete={(xhr,data)-> window.alert("Requestcomplete") } }) }
外部接口有一些限制:
它们不能在is检查的右侧使用。
as转换为外部接口总是成功(并在编译时产生警告)。
它们不能作为具体化类型参数传递。
它们不能用在类的字面值表达式(即I::class)中。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!