跳到主要内容

Dart 常见问题

本页收集了社区中的一些热门问题。

通用

#

问:Dart 有规范吗?

#

是的。ECMA-408 涵盖了 Dart 编程语言规范。

已发布五个版本。最新的进行中版本涵盖到 Dart 2.13-dev。

版本发布日期批准日期涵盖版本
第 6 版 picture_as_pdf2024 年 1 月 24 日2.13-dev
第 5 版 picture_as_pdf2021 年 4 月 9 日2.10
第 4 版 picture_as_pdf2015 年 8 月 19 日2015 年 12 月1.11
第 3 版 picture_as_pdf2015 年 4 月 15 日2015 年 6 月1.9
第 2 版 picture_as_pdf2014 年 11 月 21 日2014 年 12 月1.6
第 1 版 picture_as_pdf2014 年 3 月 27 日2014 年 6 月1.3

要了解更多关于规范的信息,请查看 Dart 语言规范页面。

问:你们如何接收有关 Dart 变更的意见?

#

团队会听取反馈、阅读问题报告,并审查贡献者提交的补丁。有良好记录的贡献者可以获得仓库的写入权限。Google 工程师也在公共仓库中工作,进行可见的变更。该项目已收到许多外部补丁,并欢迎分布式提交者。


语言

#

问:Dart 和 Java 很像吗?

#

Dart 和 Java 有一些相似之处。要查看使用熟悉语法的简短示例,请参阅 Dart 简介中的代码示例。

问:Dart 和 Go 有什么关系?

#

Google 启动了 Dart 和 Go 语言项目。这些独立的项目有不同的目标,因此做出了不同的选择。这两种语言本质上非常不同,但团队成员可以相互学习。

问:为什么 Dart 和 Haskell / Smalltalk / Python / Scala / 其他语言不像?

#

原因多种多样,取决于用于比较的语言。

与 JavaScript 的差异
Dart 必须编译为高效的 JavaScript。与 JavaScript 差异过大的源语言可能会生成复杂的输出代码来模拟源语言的行为。这会导致性能以程序员不易察觉的方式变化。
编译为原生代码的语言
Dart 优先考虑高效编译为机器码。因此,它与一些其他编译型语言有一些共同之处。
被认为比 Dart“更动态”的语言
Dart 选择牺牲一些任意的运行时修改能力,以实现更好的性能和更高效的工具。

问:为什么 Dart 语法不更有趣?

#

一些不错的语法特性确实存在,比如 this. 构造函数参数和用于单行函数的 =>。Dart 选择熟悉性而非新颖性

问:Dart 支持反射吗?

#
服务器和命令行脚本
是的,Dart 通过 mirrors API 支持反射。
Web 或 Flutter 应用
不,Dart 不支持编译到 web 或 Flutter 应用时的反射。

问:Dart 能添加我想要的语言特性吗?

#

未来版本可能包含您想要的特性。有些特性不符合语言的本质。有些特性与其他特性不兼容。简洁性是给予未来程序员最重要的礼物。

要查看是否有人已提交您的请求,请查看语言提案漏斗语言问题列表

  • 如果问题已存在,请点赞。

  • 如果问题不存在,请提交新的问题

    为您的特性提出深思熟虑的论证。为您的论证添加证据。包括使用或不使用您的特性的示例代码,或提供可观的代码库。

要了解更多信息,请参阅语言演进流程

如果 Dart 语言团队拒绝了您的请求,请不要感到惊讶。移除语言特性比添加更痛苦。Dart 语言团队首先添加最显而易见的特性,稍后再回顾下一层次的特性。

社区提出的特性请求会比任何单一语言在不变得一团糟的情况下所能满足的都要多。Dart 语言团队确实重视建议和证据。这种重视应通过仔细的设计选择和公平的沟通体现出来。


类型系统

#

问:Dart 使用静态类型吗?

#

是的,Dart 使用静态类型。要了解更多信息,请参阅 Dart 的类型系统

结合静态和运行时检查,Dart 拥有健全的类型系统。这保证了某种类型的表达式不会产生另一种类型的值。

如果您需要动态类型的灵活性,可以使用 dynamic 注解任何变量。这个 dynamic 类型是静态的,但在运行时可以包含任何类型。这会使该变量失去许多类型安全语言的好处。

问:为什么泛型是协变的?

#

协变泛型符合程序员的普遍直觉,而且这种直觉通常是正确的,例如在常见的泛型“只读”使用场景中。尽管这种直觉并非总是正确,但 Dart 通过采用协变泛型来倾向于便利性。

唯一合理的其他默认变体是不可变(invariance)。虽然只使用不可变泛型肯定会防止更多错误,但它也会阻止许多有效的程序,或者要求每次您有一个“苹果”列表而有人只想要“水果”时进行转换。

我们熟悉各种语言尝试标记或推断变体的方式。我们认为变体推断系统在 Dart 中带来的好处不足以弥补其增加的复杂性。

再再一次,我们力求务实,并且认为结果是合理的。


用法与工具

#

问:Dart 支持 JSON 吗?

#

是的。要了解更多信息,请查阅 dart:convert 库中的 JSON 转换器。

问:Dart 可以在服务器端运行吗?

#

是的。要了解更多信息,请参阅 服务器端 Dart

问:如何使用第三方代码或共享代码?

#

pub.dev 网站(Dart 和 Flutter 的包托管服务)上搜索包。使用 pub 命令打包您的代码并上传到该网站。

问:编写 Dart 代码是否需要特定的编辑器或 IDE?

#

不。您可以使用 DartPad 试用 Dart 代码,然后使用您喜欢的编辑器或 IDE 进行开发。一些功能齐全的 IDE,例如 IntelliJ IDEA、WebStorm 和 Visual Studio Code,都有 Dart 插件。许多编辑器也存在开源的 Dart 插件。有关更多信息,请参阅 Dart 工具

问:我可以用 Dart 构建 Android 应用吗?

#

是的!您可以使用 Flutter 框架和 Dart 语言构建 Android 应用。您编写的任何 Flutter 应用也可以在 iOS、Web 和桌面平台运行。

问:有哪些 Dart 在实际生产环境中的部署案例?

#

Google Ads、AdSense、AdMob 和 Google Assistant 都使用 Dart。Google 的很大一部分收入来自这些应用。在 Google 内部或外部,每个 Flutter 应用都使用 Dart。


原生执行

#

问:Dart 是单线程的吗?

#

不。在原生目标上,Dart 的 isolate API 可以在需要时启动多个执行线程。Dart VM 使用多个 CPU 核心同时运行这些线程。

Dart 的并发架构抽象了典型共享内存线程中复杂且易出错的代码。这也许解释了为什么人们误认为 Dart 是单线程的。

并发在 Dart Web 应用中的工作方式不同。要了解更多信息,请参阅 Dart 在 Web 上是单线程的吗?

问:我可以将 Dart 代码编译为原生代码吗?

#

是的。在编译针对桌面或移动设备等目标的应用时,Dart Native 包含一个带有即时 (JIT) 编译器的 Dart VM 和一个提前 (AOT) 编译器,用于生成原生代码。

上。 Flutter 框架使用 Dart 的原生编译能力来生成快速的原生应用。

问:我可以将 Dart 程序编译后在终端中运行吗?

#

是的。Dart 程序可以编译为原生代码,在 macOS 终端、Windows 命令提示符或 Linux shell 中运行。

请查阅 dart compile 文档。

问:AOT 编译的代码和 JIT 编译的代码哪个更快?

#

这取决于情况。Dart 编译代码的方式会产生具有不同性能特征的应用。

  • AOT 编译的代码启动速度快,运行时性能稳定,早期运行没有延迟。

  • JIT 编译的代码启动速度较慢,但在运行足够长时间以应用运行时优化后会达到峰值性能。


Web 执行

#

问:你们支持哪些浏览器作为 JavaScript 编译目标?

#

生产环境 Web 编译器支持以下浏览器的最新两个主要版本

  • Google Chrome
  • Microsoft Edge
  • Firefox
  • Apple Safari

上。 开发环境 JavaScript 编译器仅支持 Chrome 进行调试。

问:Dart 在 Web 上是单线程的吗?

#

有点区别。Dart Web 应用不能使用 isolate。为了实现代码并发,Web 应用使用 Web Worker。Web Worker 缺乏 isolate 的易用性和效率,并且具有不同的能力和限制。要了解更多信息,请参阅 Web 上的并发

问:任何有效的 Dart 代码都能编译为 JavaScript 吗?

#

任何有效的 Dart 代码都应能编译为 JavaScript。有些库仅在服务器或 Flutter 中运行。例如 dart:io 库。它提供了对操作系统文件和目录的访问,其 API 在浏览器中不可用。

问:为什么 Dart 有两种方式编译到 JavaScript?

#

这两种方式都使用 webdev 命令。webdev build 命令生成为生产环境优化的压缩 JavaScript。webdev serve 命令生成为调试优化的模块化 JavaScript。

要了解更多信息,请查阅 Dart JavaScript 编译器参考

问:编译到 JavaScript 时如何处理浮点数?

#

JavaScript 只有一种数字表示:IEEE-754 双精度浮点数。这意味着任何数字(无论是整数还是浮点数)都被表示为双精度数。JavaScript 具有类型化数据数组,并且从原生 Dart 类型化列表到 JavaScript 类型化数组的映射非常简单。

问:编译到 JavaScript 时 Dart 如何处理整数?

#

JavaScript 将所有数字存储为双精度数。这将整数精度限制在 53 位,取值范围为 -253 到 253。JavaScript 可以在此范围内存储整数而不会丢失精度。由于 JavaScript VM 会操作数字的内部表示,因此请保持在小整数 (SMI) 范围内。在 JavaScript 中,该范围介于 -231 到 231 之间(包括 0,即 -2,147,483,647 到 2,147,483,648)。

问:编译到 JavaScript 时如何处理类型化列表?

#

JavaScript 提供了与 Dart 类型化列表兼容的 32 位类型化数组。例如,Float32List 会映射为 Float32Array。生产环境的 JavaScript 编译器不支持 64 位整数:Int64ListUint64List。使用这些列表之一编译 Dart 代码将导致运行时异常。