title | date | author | tags | keywords | categories | reward | reward_title | reward_wechat | reward_alipay | source_url | translator | translator_url |
---|---|---|---|---|---|---|---|---|---|---|---|---|
[译]JavaScript Interop |
2014-12-24 01:57:00 -0800 |
Hadi Hariri |
官方动态 |
false |
Have a nice Kotlin! |
当使用 JavaScript,即创建一个可编译为 JavaScript 的 Kotlin 应用程序时,我们经常需要与 JavaScript 中的现有库进行互操作。虽然 Kotlin 已经为此提供了支持,但我们在 M10 中添加了更多的选项,使互操作性更加容易
在 M10 中,我们添加了动态关键字**[1]**,这样我们可以将类型声明为动态的,允许某些互操作性以前可能更麻烦。例如,当使用 jQuery,直到 M10,我们唯一的选择是使用 Kotlin 提供的强类库。至于 M10,我们现在也可以使用动态关键字
{% raw %}
{% endraw %}jquery.getJSON(KotlinCommitsURL) { commits ->
val commitsTable = jquery("#kotlin-commits")
commits.forEach { commit ->
commitsTable.append("""
<tr>
<td><a href=${commit.html_url}>${commit.sha.substring(0, 6)}</a></td>
<td>${commit.commit.message}</td>
</tr>""")
}
}
{% raw %}
{% endraw %}上述代码调用jQuery上的getJSON函数返回 GitHub 提交的列表。该函数使用带有单个参数的 lambda,即实际的提交。此列表中的每个条目依次是提交条目,其中包含自己的字段,例如html_url或commit.message。 在代码jQuery 中,提交和提交都是动态的,这意味着我们调用这些的任何东西都将在运行时被解析,即 JavaScript 解释器。这允许两件事情:
- 不必使用强类型的库来处理 jQuery
- 能够消耗以前未定义的模型
第二个功能是非常有用的,因为这意味着我们不必创建中间强类型的类来消耗 HTTP 端点。 当然,我们甚至可以使用诸如**循环的语言结构来做同样的事情,不仅使用forEach扩展功能。
{% raw %}
{% endraw %}jquery.getJSON(KotlinCommitsURL) { commits ->
val commitsTable = jquery("#kotlin-commits")
for(commit in commits) {
commitsTable.append("""
<tr>
<td><a href=${commit.html_url}>${commit.sha.substring(0, 6)}</a></td>
<td>${commit.commit.message}</td>
</tr>""")
}
}
{% raw %}
{% endraw %}为了使此代码工作,我们仍然需要将 jQuery*声明为动态的,并将其与 Kotlin 的相应本机等价物进行标记
{% raw %}
{% endraw %}native("$")
val jquery : dynamic = noImpl
{% raw %}
{% endraw %}需要noImpl,因为 Kotlin 中的不可为空的变量需要初始化,在这种情况下会引发异常,但是这并不会发生,因为它被有效地编译成 JavaScript 并在客户机上调用 - 侧。已经存在于 M10 之前的本机注释告诉 Kotlin JavaScript 中的标识符相当于什么。
当声明动态类型时,某些操作符在 JavaScript 中本地运行,例如索引访问器:
{% raw %}
{% endraw %}elements: dynamic
// in Kotlin
elements[1]
{% raw %}
{% endraw %}将编译为:
{% raw %}
{% endraw %}elements[i]
{% raw %}
{% endraw %}在 JavaScript 中。
在 M10 中添加的另一个功能是可以在 Kotlin 代码中嵌入一些本机 JavaScript 代码。我们可以使用js函数:
{% raw %}
{% endraw %} jquery.getJSON(KotlinCommitsURL) { commits ->
js("console.log('Calling JavaScript')")
val commitsTable = jquery("#kotlin-commits")
{% raw %}
{% endraw %}第二行在由编译产生的输出中插入 console.log('Calling JavaScript')*,将 JavaScript 与 Kotlin 代码相结合。
M10 还在 IntelliJ IDEA for Kotlin 中添加了语言注入支持。虽然这适用于任何字符串和任何语言,而不仅仅是 JavaScript,但是当使用js时,它肯定是有用的,允许这样做:
{% raw %}
{% endraw %}看起来像这样:
{% raw %}
{% endraw %}注入 JavaScript 语言时:
{% raw %}
{% endraw %}除了动态和js之外,我们还引入了对 JavaScript 的 nativeGetter,nativeSetter和nativeInvoke*注释的支持,我们已经覆盖了 M10 发布帖子 。
这些新功能都提供了与 JavaScript 的更好的互操作性,但是他们并没有争取继续为 JavaScript 中的现有库和框架提供强类型的支持。
[1]
“动态”是一个软关键字:
- 如果它发生在非类型上下文中,则它是一个标识符
- 在类型上下文中,当后面跟着一个点(除了将接收器类型与函数/属性名称分开的点除外)或一个尖括号<,它是一个标识符
- 在左侧的::在一个可调参考中:dynamic :: foo 意味着动态有一个正常的标识符