Использование кода 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 доступна в текущем по умолчанию бэкенде компилятора и в новом бэкенде компилятора 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.
Массивы примитивных типов
Перевод массивов примитивных типов использует 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–2022 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