从 javascript 角度看 Dart【一】

最近准备尝试下谷歌的 Flutter 开发,因此需要学习一下 dart 语言。本文主要将 javascript 和 dart 进行对比,从而帮助我们快速入门 dart 语言。

Dart 简介

Dart是谷歌开发的计算机编程语言,后来被Ecma (ECMA-408)认定为标准。它被用于web、服务器、移动应用和物联网等领域的开发。它是宽松开源许可证(修改的BSD证书)下的开源软件。Dart是面向对象的、类定义的、单继承的语言。它的语法类似C语言,可以转译为JavaScript,支持接口(interfaces)、混入(mixins)、抽象类(abstract classes)、具体化泛型(reified generics)、可选类型(optional typing)和 sound type system。

Dart 应用

Dart 语言最早提出的目的就是来做为浏览器开发语言, Google 本来打算将 Dart 的虚拟机放入浏览器中。后来没有实现,目前 Dart 可以被看做类似 typescript 一样。
在移动开发中,Google 开发的移动端 UI 框架 Flutter 采用的就是 Dart 语言。

Dart 语法

Dart 的几个基本概念

关于 Dart 语法有下面几个概念需要注意:

  • 每个变量都是一个对象,。甚至数字,函数,和null都是对象。所有对象都继承自Object 类。这一点和 js 保持一致。
  • Dart 的变量可以指定静态类型,也可以不指定,这里建议所有变量都要指明其类型。
  • Dart 支持顶级方法(例如 main()),也支持实例函数和类函数(静态函数)。 你还可以在一个方法内创建另外一个方法(nested(嵌入方法) 或者 local functions(本地方法))。
  • 同样,Dart 也支持顶级 变量,也支持实例变量和类变量(静态变量)。 实例变量有时候被称之为 值域或者属性(fields 或者 properties)。
  • Dart 有两种 运行模式: 生产模式和检测模式( production and checked)。生产模式效率高,但是测试模式可以在开发的时候帮助调试代码。

变量

对比如下:

a.png

总的来说 Numbers, String 差异不多,这里仅仅列出一些不同点。

在 dart 定义常量用关键字: final, const 两个,区别在于:

  1. final 要求变量只能初始化一次,并不要求赋的值一定是编译时常量,可以是常量也可以不是。而 const 要求在声明时初始化,并且赋值必需为编译时常量。
  2. final 是惰性初始化,即在运行时第一次使用前才初始化。而 const 是在编译时就确定值了。
    (编译时常量指的是:字面量(如数字、bool、字符串、List的字面量形式)、其它常量 或者 常量的算术运算,也可以是这些的组合形式(递归要求),简单地说常量就是可以在编译时确定的值)

注意:

  • 字符串的其他操作也和 js 一致(dart 中字符串没有 slice 方法)。
  • 在 dart 中字符串模板使用的是 单引号 ‘ ,而不是反引号 `
  • 我们可以用(’’’)来包含换行文本内容
1
2
String str = '''
换行文本内容''';

对于 List 和 Maps 上的操作,不同的地方如下。

List 的差别

添加
1
2
3
4
5
6
7
8
9
List<int> arr = [1, 2, 3, 4];
// 添加一个元素,类似 arr.push(5)
arr.add(5);
// 一次添加多项, 类似 arr.concat(5, 6, 7, 8)
arr.addAll([5, 6, 7, 8]);
// 指定位置添加元素, 类似 arr.splice(0, 0, 0);
arr.insert(0, 0);
// 指定位置添加多个元素,类似 arr.splice(0, 0, -1, -2);
arr.insertAll(0, [-1, -2])
删除
1
2
3
4
5
6
7
8
9
10
// 删除第一个匹配到的元素
arr.remove(3);
// 删除第几个元素,类似 arr.splice(1, 1);
arr.removeAt(1);
// 删除所有元素
arr.clear();
// 移除开始下标(包括)至结束下标(不包括)内的元素
arr.removeRange(1, 4);
// 移除并替换开始下标(包括)至结束下标(不包括)内的元素
arr.replaceRange(1, 4, [6, 7]);
查询 & 排序
1
2
3
4
// 返回从开始下标(包括)到结束下标(不包括)元素的列表; 类似: arr.slice(1, 3)
arr.sublist(1, 2);
// 数组随机排序
arr.shuffle();

List 的操作 和 Set 操作几乎一致,这里就不在列出 Set 了。

Maps 的差别

map 通常被称之为 dictionary 或者 hash, map 是一个无序的 key-value(键-值) 对。 map 中每个值都有一个对应的键便于访问。和 JavaScript 不同, Dart 对象不是 map。

所有属性
1
2
3
4
5
6
7
8
9
10
11
Map<String, int> map = {"a":1, "b":2, "c":3};
// 返回映射的哈希码
map.hashCode
// 映射上是否没有键值对
map.isEmpty
// 映射上是否有键值对
map.isNotEmpty
// 返回映射的所有键, 类似 Object.keys(map)
map.keys
// 返回对象运行时的类型
map.runtimeType

注意:这里的 Map 并不像是简单的 js 的对象。如果你想访问属性建议使用 [] 的方式,例如:map["a"]。不要使用 . 的方式 (在 Map 作为参数的时候会报错);

常用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 按顺序迭代映射
map.forEach((key, value){
print(key + " : " + value.toString());
});
// 添加其他键值对到映射中
map.addAll({"d":4, "e":5});
// 映射是否包含指定键
map.containsKey("d");
// 映射是否包含指定值
map.containsValue(5);
// 删除指定键值对
map.remove("a");
// 删除所有键值对
map.clear();
// 如果想在 key 不存在的时候 才设置该值,则可以用 putIfAbsent() 函数。该函数 的参数为返回设置的值的方法
m.putIfAbsent("d", () => 4);

函数

在 Dart 中函数的基本语法和 JavaScript 类似,但是不需要输入 function 关键字,定义一个函数:

1
2
3
void printNumber(int num) {
print(num);
}

可选参数

在 dart 中,比 js 多一个 可选参数的概念;可选参数可以是 命名参数 或者 位置参数,但是不能同时使用两种类型。

可选 - 命名参数

用 {param1, param2, …} 来定义方法的 命名参数:

1
2
3
4
void text({int a, int b}) {
print(a);
print(b);
}

注意:对于这种方式如果想要设置参数默认值,需要用 : ; 其他的情况,我们可以采用 = 来设置默认值。

1
2
3
void text({int a: 1, int b}) {
//...
}

当我们想给参数 b 设置内容的时候,调用如下:

1
text(b: 5); // 输出 null, 5
可选 - 位置参数

位于 [] 中间的参数为可选位置 参数:

1
2
3
void setPersonInfo(String name, int age, [String addr]) {
//....
}

main 函数

每一个应用都必须有一个顶级函数main() ,这个函数就是整个应用的入口函数。main() 函数返回值类型为 void 并且有一个可选参数List ,这点也是和 js 完全不同的。

语法作用域

Dart 是一种语法作用域语言,也就是说 变量的作用域 是根据代码布局静态判断的。 可以根据“变量位于花括号内外”来判断一个变量是否在作用域中。

语法闭包

一个 closure(闭包) 是一个可以 访问位于其语法作用域内变量的方法对象,即时该方法用在其定义的作用域之外,也可以访问这些变量。方法可以覆盖定义在附近作用域的变量。

匿名函数

对于只有一个表达式的方法,你可以用缩写形式:
printNumber(number) => print(‘The number is $number.’);

1
printNumber(num number) => print('The number is $number.');

但是请注意,和 js 不同,dart 只有简写的时候 => 才是函数,如果不是简写,不能用这个 => 来表示一个函数。在 Dart 中,匿名函数是没有 => 的形式。 例如,匿名函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// IIFE
// 在 javascript 这是正确的
(() => {
console.log(1);
})()
// 在 Dart 中
() {
print(1);
}();
lists.forEach((item) {
//....
})

总结

本文介绍了,Dart 的基础语法部分。对于运算符,循环,判断等就不介绍了,因为和 js 一样。总的来看,Dart 和 js 语法相似度还是很高的。下篇,讲介绍 类与泛型。