6.2.2.10 JS 普通对象编译器插件
原文链接: https://kotlinlang.org/docs/js-plain-objects.html
6.2.2.10 JS 普通对象编译器插件
实验性-通用
JavaScript (JS) 普通对象编译器插件(js-plain-objects)让你以类型安全的方式创建和复制普通 JS 对象。
这里你可以了解普通 JS 对象的相关信息,以及如何在 Kotlin/JS 项目中使用 js-plain-objects 编译器插件。
警告: js-plain-objects 插件只能与新的 K2 Kotlin 编译器一起使用。
普通 JS 对象
普通对象是通过对象字面量({})创建的、包含数据属性的简单 JS 对象。许多 JS API 都用普通 JS 对象进行配置或数据交换。
使用 js-plain-objects 插件时,你声明一个 Kotlin 外部接口来描述对象的形状,并用 @JsPlainObject 标注它。编译器随后会生成便捷函数来构建和复制这类对象,同时保持 Kotlin 的类型安全。
启用插件
把 js-plain-objects 插件添加到项目的 Gradle 配置文件中,如下面的 Kotlin DSL 所示:
Kotlin
1
2
3
4
5
6
7
8
9
10
11
| // build.gradle.kts
plugins {
kotlin("multiplatform") version "2.4.20"
kotlin("plugin.js-plain-objects") version "2.4.20"
}
kotlin {
js {
browser() // 或者 nodejs()
}
}
|
Groovy
1
2
3
4
5
6
7
8
9
10
11
| // build.gradle
plugins {
id 'org.jetbrains.kotlin.multiplatform' version '2.4.20'
id 'org.jetbrains.kotlin.plugin.js-plain-objects' version '2.4.20'
}
kotlin {
js {
browser() // 或者 nodejs()
}
}
|
声明普通对象类型
启用 js-plain-objects 插件后,你就可以声明普通对象类型。用 @JsPlainObject 标注一个外部接口。例如:
1
2
3
4
5
6
7
| @JsPlainObject
external interface User {
val name: String
val age: Int
// 可以用可空类型把属性声明为可选
val email: String?
}
|
当插件处理这样的接口时,它会生成一个包含两个辅助函数的伴生对象,用于创建和复制对象:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| @JsPlainObject
external interface User {
val name: String
val age: Int
val email: String?
// 由插件生成
@JsExport.Ignore
companion object {
inline operator fun invoke(name: String, age: Int, email: String? = NOTHING): User =
js("({ name: name, age: age, email: email })")
inline fun copy(source: User, name: String = NOTHING, age: Int = NOTHING, email: String? = NOTHING): User =
js("Object.assign({}, source, { name: name, age: age, email: email })")
}
}
|
从上面的例子可以看到:
name 和 age 声明时没有可空标记,因此是必填的。email 声明为可空,因此是可选的,创建时可以跳过。- 运算符
invoke 会用提供的属性构建一个新的普通 JS 对象。 copy 函数通过对 source 进行浅复制并覆盖指定的属性来创建新对象。- 伴生对象用
@JsExport.Ignore 标记,以避免把这些辅助函数泄漏到 JS 导出中。
使用普通对象
使用生成的辅助函数创建和复制对象:
1
2
3
4
5
6
7
8
9
| fun main() {
val user = User(name = "Name", age = 10)
val copy = User.copy(user, age = 11, email = "some@user.com")
println(JSON.stringify(user))
// { "name": "Name", "age": 10 }
println(JSON.stringify(copy))
// { "name": "Name", "age": 11, "email": "some@user.com" }
}
|
这段 Kotlin 代码会编译为 JavaScript:
1
2
3
4
5
6
7
8
9
| function main () {
var user = { name: "Name", age: 10 };
var copy = Object.assign({}, user, { age: 11, email: "some@user.com" });
println(JSON.stringify(user));
// { "name": "Name", "age": 10 }
println(JSON.stringify(copy));
// { "name": "Name", "age": 11, "email": "some@user.com" }
}
|
用这种方式创建的任何 JavaScript 对象都是安全的。当你用错属性名或值类型时,会遇到编译期错误。这种方式也是零开销的,因为生成的代码会被内联为简单的对象字面量和 Object.assign 调用。
接下来学什么
在从 Kotlin 使用 JavaScript 代码和动态类型文档中进一步了解与 JavaScript 的互操作。