Использование кода Kotlin из JavaScript
В зависимости от выбранной системы модулей JavaScript, компилятор Kotlin/JS генерирует различный вывод. Но в целом, компилятор Kotlin генерирует обычные JavaScript-классы, функции и свойства, которые можно свободно использовать из JavaScript-кода. Однако есть некоторые тонкости, которые следует помнить.
Изоляция объявлений в отдельном JavaScript-объекте в простом режиме
Если вы явно установили тип модуля в 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 к объявлению верхнего уровня (например, к классу или функции), вы делаете объявление Kotlin доступным из JavaScript. Аннотация экспортирует все вложенные объявления с именем, заданным в Kotlin. Она также может быть применена на уровне файла с помощью @file:JsExport.
Для разрешения неоднозначностей в экспорте (например, перегрузки функций с одинаковым именем) можно использовать аннотацию @JsExport совместно с @JsName для указания имен сгенерированных и экспортированных функций.
Аннотация @JsExport доступна в текущем по умолчанию компиляторе back-end и новом back-end компилятора IR. Если вы используете back-end компилятора 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.
Примитивные массивы
Перевод примитивных массивов использует 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–2023 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/js-to-kotlin-interop.html