Вызов Kotlin из JavaScript
В зависимости от выбранной системы модулей JavaScript, компилятор Kotlin/JS генерирует различный вывод. Но в общем случае компилятор Kotlin генерирует обычные JavaScript-классы, функции и свойства, которые вы можете свободно использовать из кода JavaScript. Однако следует помнить о некоторых нюансах.
Изоляция объявлений в отдельном JavaScript-объекте в режиме plain
Если вы явно установили тип модуля в plain, Kotlin создаёт объект, содержащий все объявления Kotlin из текущего модуля. Это делается для предотвращения загрязнения глобального объекта. Это означает, что для модуля myModule, все объявления доступны JavaScript через объект myModule. Например:
fun foo() = "Hello"
Это можно вызвать из JavaScript так:
alert(myModule.foo());
Это не применимо, когда вы компилируете свой Kotlin-модуль в JavaScript-модули, такие как UMD (по умолчанию для browser и nodejs целей), CommonJS или AMD. В этом случае ваши объявления будут экспортированы в формате, заданном выбранной системой JavaScript-модулей. Например, при использовании UMD или CommonJS место вызова может выглядеть так:
alert(require('myModule').foo());
Дополнительную информацию о системах JavaScript-модулей см. в статье о JavaScript-модулях.
Структура пакетов
Kotlin экспортирует структуру своих пакетов в JavaScript, поэтому, если вы не определяете свои объявления в корневом пакете, вам нужно использовать полные квалифицированные имена в JavaScript. Например:
package my.qualified.packagename fun foo() = "Hello"
При использовании UMD или CommonJS, например, место вызова может выглядеть так:
alert(require('myModule').my.qualified.packagename.foo())
Или, в случае использования plain в качестве настройки системы модулей:
alert(myModule.my.qualified.packagename.foo());
@JsName аннотация
В некоторых случаях (например, для поддержки перегрузок) компилятор Kotlin изменяет имена сгенерированных функций и атрибутов в JavaScript-коде. Для управления сгенерированными именами вы можете использовать аннотацию @JsName.
// Module 'kjs'
class Person(val name: String) {
fun hello() {
println("Hello $name!")
}
@JsName("helloWithGreeting")
fun hello(greeting: String) {
println("$greeting $name!")
}
}
Теперь вы можете использовать этот класс из JavaScript следующим образом:
// If necessary, import 'kjs' according to chosen module system
var person = new kjs.Person("Dmitry"); // refers to module 'kjs'
person.hello(); // prints "Hello Dmitry!"
person.helloWithGreeting("Servus"); // prints "Servus Dmitry!"
Если мы не указали аннотацию @JsName, имя соответствующей функции будет содержать суффикс, рассчитанный по сигнатуре функции, например hello_61zpoe$.
Обратите внимание, что существуют случаи, когда компилятор Kotlin не применяет изменение имён:
- Объявления
externalне изменяются. - Любые переопределённые функции в не-
externalклассах, наследующих отexternalклассов, не изменяются.
Аргумент @JsName должен быть константной строковой литеральной, являющейся допустимым идентификатором. Компилятор сообщит об ошибке при попытке передать в @JsName неидентификаторную строку. Следующий пример приводит к ошибке во время компиляции:
@JsName("new C()") // error here
external fun newC()
@JsExport аннотация
Аннотация
@JsExportв настоящее время отмечена как экспериментальная. Её дизайн может измениться в будущих версиях.
Применяя аннотацию @JsExport к объявлениям верхнего уровня (например, к классу или функции), вы делаете объявление Kotlin доступным из JavaScript. Аннотация экспортирует все вложенные объявления с именем, заданным в Kotlin. Она также может быть применена на уровне файла с помощью @file:JsExport.
Для разрешения неоднозначностей в экспорте (например, перегрузки функций с одинаковым именем) вы можете использовать аннотацию @JsExport вместе с @JsName для указания имён сгенерированных и экспортированных функций.
Аннотация @JsExport доступна в текущем стандартном компиляторе бэкенде и в новом бэкенде компилятора IR. Если вы используете бэкенд компилятора IR, вы должны использовать аннотацию @JsExport для того, чтобы сделать ваши функции видимыми из Kotlin в первую очередь.
В многоплатформенных проектах @JsExport доступна и в коде общего использования. Она действует только при компиляции для JavaScript-цели и позволяет экспортировать объявления Kotlin, которые не зависят от платформы.
Представление типов Kotlin в JavaScript
- Числовые типы Kotlin, кроме
kotlin.Long, отображаются в 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. -
kotlin.Longне отображается ни в один JavaScript-объект, так как в JavaScript нет 64-битного целочисленного типа. Он эмулируется классом 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.
Начиная с версии 1.1.50, преобразование примитивных массивов использует JavaScript TypedArray:
-
kotlin.ByteArray,-.ShortArray,-.IntArray,-.FloatArray, и-.DoubleArrayотображаются соответственно в JavaScript Int8Array, Int16Array, Int32Array, Float32Array и Float64Array. -
kotlin.BooleanArrayотображается в JavaScript Int8Array со свойством$type$ == "BooleanArray" -
kotlin.CharArrayотображается в JavaScript UInt16Array со свойством$type$ == "CharArray" -
kotlin.LongArrayотображается в JavaScript Array изkotlin.Longсо свойством$type$ == "LongArray".
© 2010–2020 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/reference/js-to-kotlin-interop.html