概述
Dart 是一门强类型、多范式(面向对象、函数式编程)、单线程事件驱动、跨平台(mobile、web、server)的语言。它同时支持 JIT 和 AOT 编译,这使得它具备开发时和运行时的高效率。
Dart 的语法非常简洁现代化,从中可以看到很多 ES6+ 语法的影子。下面我们从 一名前端工程师的角度看看这门语言。
语法
变量声明
dart 中支持 var const final 三种变量声明方式,var 和 Java 中一样支持类型推断。
强类型
Dart 支持编译时和运行时的强类型检查,借助 Dart 的类型推断,我们编码时也可以省略一些类型注解(typescript 和 Java 中也有类似的技术)。强类型使我们的代码更健壮、可读、可维护,并且拥有更高的运行时性能。
和 typescript 一样,Dart 也支持泛型和 any(Dart 中叫 dynamic),也可以通过 as 关键字进行类型转换。
类型系统
在 Dart 中一切皆对象,每个对象都要自己的类(包括 null、function 甚至一些我们 JS 中所谓的基本类型)。每个对象都继承于 Object 类。
和 JS 一样,Dart 也内置了 number string Boolean List Map Set Symbol 类型。不同的是, Dart 的 number 同时支持 int 和 double 两种数字类型。另外 Dart 还通过 Runes 类型支持 UTF-32 编码的字符串。
main() {
var clapping = '\u{1f44f}';
print(clapping);
print(clapping.codeUnits);
print(clapping.runes.toList());
Runes input = new Runes(
'\u2665 \u{1f605} \u{1f60e} \u{1f47b} \u{1f596} \u{1f44d}');
print(new String.fromCharCodes(input));
}
和 typescript 一样,dart 也支持 enum 声明一个 enum
enum Color { red, green, blue }
获取 enum 的 list
List<Color> colors = Color.values;
assert(colors[2] == Color.blue);
enum 在 switch 语句中很好用
var aColor = Color.blue;
switch (aColor) {
case Color.red:
print('Red as roses!');
break;
case Color.green:
print('Green as grass!');
break;
default: // Without this, you see a WARNING.
print(aColor); // 'Color.blue'
}
函数
之前说了函数在 dart 中也是一种对象,所以函数也可以作为另一个函数的参数。和 JS 一样 Dart 也支持可选参数、默认参数、箭头函数、词法作用域和闭包。
不同的是, dart 中有一个特殊的 main 函数作为整个应用的入口。
操作符
dart 支持 js 中绝大多数的操作符,如数字运算、取余,== 、!= 、>=、类型判断(is)、赋值语句、与或非、属性访问符 [] .、可选属性访问符 ?.
另外 Dart 中还有一些语法糖:
JS中的 ||
String playerName(String name) => name ?? 'Guest';
整除,类似 Python 中的 //
assert(5 ~/ 2 == 2); // Result is an int
链式调用 ..
querySelector('#confirm') // Get an object.
..text = 'Confirm' // Use its members.
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
控制流
这方面 dart 和 js 差别很小。
if else for while switch等语句都支持,另外支持 assert 语句
异常处理
和 js 一样,dart 支持 throw try catch finally 语句。另外,dart 中用 on 来指定特定错误类型的处理分支
try {
breedMoreLlamas();
} on OutOfLlamasException {
// A specific exception
buyMoreLlamas();
} on Exception catch (e) {
// Anything else that is an exception
print('Unknown exception: $e');
} catch (e) {
// No specified type, handles all
print('Something really unknown: $e');
}
面向对象
dart 是一门面向对象的语言,支持单继承和 mixin,也支持 抽象类。
不同的是,dart 中构造方法支持重定向、工厂(好像没啥卵用)
class Logger {
final String name;
bool mute = false;
// _cache is library-private, thanks to
// the _ in front of its name.
static final Map<String, Logger> _cache =
<String, Logger>{};
factory Logger(String name) {
return _cache.putIfAbsent(
name, () => Logger._internal(name));
}
Logger._internal(this.name);
void log(String msg) {
if (!mute) print(msg);
}
}
另外,dart 中的 class 同时也是一样隐式的 interface,也就说 classA 被 extends 时是 class,被 implements 时是 interface。
泛型
和ts一样,dart 中支持泛型,泛型的意义在于兼顾代码复用和类型安全。
abstract class Cache<T> {
T getByKey(String key);
void setByKey(String key, T value);
}
异步编程
和 js 一样,dart 是一门单线程、事件驱动的语言,非常适合前端和客户端开发。它的单线程模型和 js 很类似:

具体到 dart 中的异步队列,又分为事件队列和微任务队列。可以类比 js 中的宏任务和微任务。

关于异步语法,dart 支持 async await,使用 Future 替代 js 中的 Promise。我们也可以使用 try catch 捕获异步中的错误。
不同的是,Future 只有两种状态 Uncompleted 和 Completed (成功或者报错)。
void printOrderMessage () async {
try {
var order = await fetchUserOrder();
print('Awaiting user order...');
print(order);
} catch (err) {
print('Caught error: $err');
}
}
Future<String> fetchUserOrder() {
// Imagine that this function is more complex.
var str = Future.delayed(Duration(seconds: 4), () => throw 'Cannot locate user order');
return str;
}
Future<void> main() async {
await printOrderMessage();
}
和 node 和 Java 一样,dart 中也有 Stream 的概念,比如一个简单的 http server
Future main() async {
var server = await HttpServer.bind(
InternetAddress.loopbackIPv4,
4040,
);
print('Listening on localhost:${server.port}');
await for (HttpRequest request in server) {
request.response.write('Hello, world!');
await request.response.close();
}
}
并发编程
dart 通过 Isolates 来支持并发编程,和浏览器中的 web Worker 线程不同,每个 isolates 拥有独立的内存、事件循环。
装饰器
dart 支持装饰器。
class Television {
/// _Deprecated: Use [turnOn] instead._
@deprecated
void activate() {
turnOn();
}
/// Turns the TV's power on.
void turnOn() {...}
}
模块系统
在 dart 中,我们通过 import 来引入模块,
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
// Uses Element from lib1.
Element element1 = Element();
// Uses Element from lib2.
lib2.Element element2 = lib2.Element();
也可以异步加载一个模块,和 js 中的 import() 类似:
import 'package:greetings/hello.dart' deferred as hello;
// 需要调用时
Future greet() async {
await hello.loadLibrary();
hello.printGreeting();
}
loadLibrary 可以多次调用,但模块本身只会加载一次。
标准库
Dart 有非常优秀的标准库,比如
跨平台的标准库:
dart:collection 覆盖了日常开发中的数据结构
dart:convert 编解码、序列化、反序列化
dart:developer 用于 debug 和 检查
dart:math 同 js 中的 math
native 标准库
dart:io 网络请求和io
dart:isolate 并发编程
dart:mirrors 反射
web 中使用的标准库
包含了 html index_db web_gl 等功能
开发工具
dart 提供了很多开发工具来辅助我们日常开发。
模块管理
类似 npm maven ,dart 中提供 pub 来管理依赖,pubspec.yaml 来描述项目的依赖模块。
Command-line
可以用来编译和运行 dart 文件,类似 nodejs。 通过官网安装dart SDK: dart.dev/get-dart
debug
devtools
代码静态分析
dartanalyzer
代码 format
dartfmt
文档生成
dartdoc
自动化测试
package:test/test.dart
总结
Dart 是一门简洁实用、现代化的语言。它吸收了 JavaScript 中的事件驱动思想并提供强大灵活的类型系统,它拥有简洁的并发模型、优秀的标准库和开发工具支持。
Dart 强调实用,并不追求所谓的编程哲学,它吸收了众多语言的优秀思想,并且没有 JavaScript 的历史包袱。我个人比较喜欢它的类型系统、标准库和测试、代码静态分析工具。
它的缺点也很明显,它是一门 ”普通“ 的现代化语言,没什么让 JavaScript 开发者动心的亮点。AOT 编译很好,性能很强大,但 web 应用的性能瓶颈并不在于 JavaScript。在 flutter 爸爸出现之前,它定位是 JavaScript 的替代品,但没有干过 typescript + JS 强大的生态。总的来说,它不是JavaScript